泛型不仅限于类,还将用于委托、接口和方法的泛型。
泛型并不是一个全新的结构,其他语言中有类似的概念。例如,C++模板就与泛型相当。但是,C++模板和.NET 泛型之间有一个很大的区别。对于 C++模板,在用特定的类型实例化模板时,需要模板的源代码。相反,泛型不仅是 C#语言的一种结构,而且是 CLR 定义的。所以,即使泛型类是在C#中定义的,也可以在 Visual Basic 中用一个特定的类型实例化该泛型。
性能
泛型的一个主要优点是性能。对值类型使用非泛型集合类,在把值类型转换为引用类型,和把引用类型转换为值类型时,需要进行装箱和拆箱操作。值类型存储在堆栈上,引用类型存储在堆上。
类型安全性
泛型的另一个特性是类型安全。
代码重用
泛型允许更好地重用二进制代码。
代码的扩展
因为泛型类的定义会放在程序集中,所以用某个类型实例化泛型类不会在 IL 代码中复制这些类。
命名约定
public class LinkedListNode<T>
{
private T value;
public LinkedListNode(T value)
{
this.value = value;
}
public T Value
{
get { return value; }
}
private LinkedListNode<T> next;
public LinkedListNode<T> Next
{
get { return next; }
internal set { next = value; }
}
private LinkedListNode<T> prev;
public LinkedListNode<T> Prev
{
get { return prev; }
internal set { prev = value; }
}
}
在创建泛型类时,需要一些其他 C#关键字。例如,不能把 null 赋予泛型类型。此时,可以使用default 关键字。
使用泛型可以定义接口,接口中的方法可以带泛型参数。在链表示例中,就执行了 IEnumerable
接口,它定义了 GetEnumerator()方法,以返回 IEnumerator。
public interface IComparable<T>
{
int CompareTo(T other);
}
除了定义泛型类之外,还可以定义泛型方法。在泛型方法中,泛型类型用方法声明来定义。
void Swap<T>(ref T x, ref T y)
{
T temp;
temp = x;
x = y;
y = temp;
}
int i = 4;
int j = 5;
Swap<int>(ref i, ref j);
Swap(ref i, ref j);
委托是类型安全的方法引用。通过泛型委托,委托的参数可以在以后定义。
public sealed delegate void EventHandler(object sender, TEventArgs e) where TEventArgs : EventArgs
除了 System.Collections.Generic 命名空间之外,.NET Framework 还有其他泛型类型。这里讨论的结构和委托都位于 System 命名空间中,用于不同的目的。