跟不是范型的类型类似,编译后的范型也表现为IL指令和元数据.当然范型也会编码已存在和使用的类型参数.
在构造范型类型,比如stack<int>的实例在程序中被构造时,.NET的CLR JIT编译器将会把IL指令和元数据转化成本地代码,在这个过程中将会用实际类型替换类型参数.以后对该构造范型类型的引用将会使用同一份本地代码.从范型类型创建一个特定的构造范型类型的过程叫做范型类型的实例化(Generic Type Instantiation).
.NET运行时会为每个用值类型进行的范型的实例化创建一份特定的本地代码拷贝,但是用引用类型进行的范型的实例化会共享一份本地代码(因为在本地代码层次,引用是具有同样表现形式的指针).
4.约束
如果想用type parameters 调用某些方法会出现什么情况那?
public class Dictionary<K,V>
{
public void Add(K key, V value)
{


if (key.CompareTo(x) < 0) {
} // Error, no CompareTo method


}
}
public class Dictionary<K,V>
{
public void Add(K key, V value)
{


if (((IComparable)key).CompareTo(x) < 0) {
}


}
}
为了支持更强的编译时检查和减少类型转化带来的开销,C#允许为每个类型参数提供一个可选的约束(Constraints)列表.Constraints的定义以where+类型参数+类或者接口类型的类表[+构造器约束new()].
对于范型Dictionary<K,V>为了确保其中的keys实现IComparable接口,可以对K做一个约束.
public class Dictionary<K,V> where K: IComparable
{
public void Add(K key, V value)
{


if (key.CompareTo(x) < 0) {
}


}
}
5.范型方法
在某些情况下,并不需要整个类是范型,而只需要某个类的方法成员是范型的.这经常发生在当把一个范型类型做为一个方法的参数时.比如Stack<T>这个范型,当想把一组中的多个值一次性压入栈的时候,写一个方法把这些值在一个方法调用时实现这个功能是比较方便的.对于一个给定的构造类型,比如Stack<int>,这个方法可以用如下方式定义:
void PushMultiple(Stack<int> stack, params int[] values) {
foreach (int value in values) stack.Push(value);
}
void PushMultiple<T>(Stack<T> stack, params T[] values) {
foreach (T value in values) stack.Push(value);
}
Stack<int> stack = new Stack<int>();
PushMultiple<int>(stack, 1, 2, 3, 4);
Stack<int> stack = new Stack<int>();
PushMultiple(stack, 1, 2, 3, 4);
