《c#高级编程》第2章C#2.0中的更改(一)——泛型

一、实例

当我们需要编写一些通用的代码,但是不确定它们将处理的数据类型时,泛型就非常有用了。下面是一个简单的 C# 泛型示例:

using System;

public class Example
{
    public static void Main()
    {
        // 定义一个 int 数组
        int[] ints = { 1, 2, 3, 4, 5 };

        // 输出数组的所有元素
        Console.WriteLine("Integers:");
        PrintArray(ints);

        // 定义一个 string 数组
        string[] strings = { "hello", "world", "!" };

        // 输出数组的所有元素
        Console.WriteLine("\nStrings:");
        PrintArray(strings);
    }

    // 使用泛型方法输出数组的所有元素
    public static void PrintArray<T>(T[] array)
    {
        foreach (T element in array)
        {
            Console.Write("{0} ", element);
        }
        Console.WriteLine();
    }
}

 

这个示例展示了泛型的核心思想 - 通过使用类型参数来实现通用性。使用泛型,我们可以编写一次性代码,以处理多种类型的数据,并且不必对每种数据类型都编写一份独立的代码。

总之,C# 泛型是一种非常强大的特性,它提高了代码的通用性和可重用性,同时避免了装箱和拆箱的性能损失。

二、基本原理

当我们定义一个泛型类或方法时,编译器会生成两个相关的实体 - 泛型类型和泛型方法。泛型类型用于描述包含类型参数的类型,而泛型方法则用于描述包含类型参数的方法。

在运行时,C# 的实现机制采用了类型擦除的策略。具体来说,在泛型类型和泛型方法被调用时,CLR(Common Language Runtime)会将其中的类型参数替换为实际的类型,并对其进行检查和转换操作。这个过程称为类型擦除。

例如,如果我们定义了以下泛型 List<T> 类:

```
class List<T>
{
private T[] array;

public List()
{
array = new T[10];
}

public void Add(T item)
{
// ...
}
}
```

那么在编译期间,编译器会生成一个非泛型类,它与上面的泛型类相似,但是使用 object 类型替换了 T 类型:

```
class List
{
private object[] array;

public List()
{
array = new object[10];
}

public void Add(object item)
{
// ...
}
}
```

当我们创建一个 List<int> 实例并调用 Add 方法时,CLR 会将类型参数 int 替换为实际的类型,并执行必要的类型检查和转换操作,然后执行相应的代码。

这个过程确保了泛型代码在运行时能够像普通代码一样执行,同时避免了代码重复。由于泛型类型和泛型方法只需要编译一次,因此它们在性能方面具有优势,并且不会占用额外的存储空间。

希望这个解释能够让你更好地理解 C# 泛型的实现过程。

 

posted @ 2023-04-24 21:10  GroundSoft  阅读(27)  评论(0编辑  收藏  举报