首页 > 编程笔记 > C#笔记

什么是泛型,C#泛型详解

泛型实质上就是使程序员定义安全的类型。

在没有出现泛型之前,C# 提供了对 Object 的引用“任意化”操作。但这种任意化操作在执行某些强制类型转换时,有的错误也许不会被编译器捕捉,而在运行后出现异常。由此可见,强制类型转换存在安全隐患,所以 C# 提供了泛型机制。

本节就带着大家详细了解 C# 的泛型机制。

为什么要使用泛型

我们在开发程序时,经常会遇到功能非常相似的模块,只是它们处理的数据不一样。通常的处理方法是编写多个方法来处理不同的数据类型,那么有没有一种办法,可以用同一个方法来处理传入的不同类型参数呢?泛型就可以解决这类问题。

例如,下面代码定义了 3 个方法,分别用来获取 int、double 和 bool 类型的原始类型。
public void GetInt(int i)
{
    Console.WriteLine(i.GetType());
}
public void GetDouble(double i)
{
    Console.WriteLine(i.GetType());
}
public void GetBool(bool i)
{
    Console.WriteLine(i.GetType());
}
调用上面方法的代码如下:
Program p = new Program();
p.GetInt(1);
p.GetDouble(1.0);
p.GetBool(true);
运行结果如下:
System.Int32
System.Double
System.Boolean
观察上面的代码可以发现,除了传入的参数类型不同外,它们实现的功能是一样的。这时有人可能会想到 object 类型,可以将上面的代码优化成如下形式。
public void GetType(object i)
{
    Console.WriteLine(i.GetType());
}
上面优化的代码可以实现与第一段代码相同的功能,但是使用 object 会对程序的性能造成影响。遇到这种情况应该怎么办呢?泛型可以解决这个问题。

C#泛型类型参数

在定义泛型时,只需要指定泛型的类型参数,通常用 T 表示。它可以看作一个占位符,而不是一种类型,仅代表了某种可能的类型。在定义泛型时,T 出现的位置可以在使用时用任何类型来代替。

类型参数 T 的命名准则如下。

1) 使用描述性名称命名泛型类型参数,除非单个字母名称完全可以让人了解它表示的含义。例如,使用代表一定意义的单词作为类型参数T的名称,代码如下。
public interface IStudent<TStudent>
public delegate void ShowInfo<TKey, TValue>

2) 将T作为描述性类型参数名的前缀。例如,使用T作为类型参数名的前缀,代码如下:
public interface IStudent<T>
{
    T Sex { get; }
}
例如,可以将前面章节中获取各种数据原始类型的代码优化成如下形式:
public void GetType<T>(T t)
{
    Console.WriteLine(t.GetType());
}
调用的代码可以修改成如下形式:
Program p = new Program();
p.GetType<int>(1);
p.GetType<double>(1.0);
p.GetType<bool>(true);
为什么使用泛型可以解决上面的问题呢?这是因为泛型是延迟声明的,即在定义时并不需要明确指定具体的参数类型,而是把参数类型的声明延迟到了调用时才指定。这里需要注意的是,在使用泛型时,必须指定具体类型。

C#泛型方法

其实上面在优化获取各种数据原始类型的代码时,已经用到了泛型方法。泛型方法就是指在声明中包含类型参数 T 的方法,其语法格式如下:
修饰符 void 方法名<类型参数T>(参数列表)
{
    方法代码
}

例如,定义一个泛型方法,获取一维数组中的元素值,代码如下:
public void GetValue<T>(T[] ts)
{
    for (int i = 0; i < ts.Length; i++)
        Console.WriteLine(ts[i]);
}

C#泛型类

除了方法可以是泛型的以外,类也可以是泛型的。

泛型类的声明形式如下:
修饰符 class 类名<T>
{
    类代码
}
声明泛型类与声明一般类的唯一区别是增加了类型参数<T>

例如,定义一个泛型类 Test<T>,在该类中定义一个泛型类型的变量,代码如下。
public class Test<T>//创建一个泛型类
{
    public T _T;//公共变量
}
定义泛型类之后,如果要使用该类,则需要在创建对象时指定具体的类型,例如下面的代码:
// T是int类型
Test<int> testInt = new Test<int>();
testInt._T = 123;
// T是string类型
Test<string> testString = new Test<string>();
testString._T = "123";

说明以下几点:

推荐阅读