编辑文章 - 博客频道 - CSDN.NET
1.什么泛型
泛型出现的真正意义在于,类型能在运行时指定类型参数。在没有泛型的时候很多算法相同但是传入类型不同的方法需要反复的出现在不同的类里面,增加了工作量,并且在维护过程中的代价也是非常的巨大,在这样的情况下如果方法能够在运行时指定类型那么就可以降低很多的工作量,所以“懒惰”的软件工程师设计出了可以获取类型参数的方法“泛型”。
利用泛型,可以在声明变量时创建用来处理特定类型的特殊数据结构。程序员定义这种参数化类型,使特定泛型类型的每个变量都有相同的内部算法。
2.泛型的类型
在定义一个类型时,使用另一个或几个类型作为参数,类型参数用<>围住,放在所定义的类型名后面。
使用带有类型参数的泛型类型时,参数具体类型指定。
class Stack<T> { private T[] m_ItemArray; }
这样定义一个泛型类型,在我们需要使用该类型的时候,我们就在实例化该类型的时候指定该对象的类型比如:上面我们的类型我们要声明一个String类型
Stack<string> s=new Stack<string>();
这样我们就实现了在程序需要的时候动态传入需要的类型参数。其实C#的很多类型都已经支持泛型,比如我们常用的List对象他可以动态指定类型的原因就是因为他内部是由泛型实现的。而且在.NetFramework3.5之后引入了Linq查询表达式,其中linq都有两套方法一套是普通实现另一种是泛型实现的,所以Linq中支持多种类型的查询。
又比如在一个类型中重复一个接口的实现,只要这个接口的传入类型为不一样的。
public interface IContainer<T> { ICollection<T> Items { get;set; } } public class Person:IContainer<Address>,IContainer<Phone> { ICollection<Address> IContainer<Address>.Items { get{.....} set{.....} } ICollection<Phone> IContainer<Phone>.Items { get{.....} set{.....} } }
定义了一个泛型接口IContainer类型里面的属性实现也是一个泛型类型,他们同样类型来自于同一个类型。然后再Person类型中我要实现两个Icontainer类型一个指定Address类型另一个指定为Phone类型,这样就导致不会冲突了,然后里面的属性实现也是不同的两套,这两套分别来自各自传入类型的类型。
3.泛型约束
对泛型接收参数的一些特性进行限制。泛型类中声明的每一个类型参数提供一个可选的约束条件。 使用泛型后面添加where语句限制。
3.1. 值类约束:要求泛型参数必须是值类型,例如int,short或自定义的struct
public class MyClass<T> where T:struct {}
定义接收参数的类型如果不为struct是不会被接收的。3.2.引用类型约束:要求泛型阐述必须是引用类型。例如string,object 和自定义class
public class MyClass<T> where T:class //这个泛型类只接受引用类型的泛型参数。 {}
定义接收参数的类型如果不为class是不会被接收的。
3.3.构造函数约束:要求泛型参数必须有构造函数
public class MyClass<T> where T:new() {}
如果传入参数类型没有定义构造函数,类型是不能被实例化的。3.4.接口约束:要求泛型参数必须实现某个接口
public class MyClass<T> where T:System.IComparable {}
3.5基类约束:要求泛型参数必须继承某个基类public class MyClass<T> where T:Customer {}
如果没有这些约束,在使用中会因为界限不明确或条件不清楚导致一些很难调试的问题,使用约束就可以很好的界定每一个泛型可接收类型的条件并明确了这些泛型类型的使用范围。可以很好的对泛型类型的管理和界定。
4.泛型内部机制
泛型类的“类型参数”编程了元数据,“运行时”在需要的时候会利用它们构造恰当的类。所以泛型支持继承、多态以及封装。泛型类型经过编辑器编译之后生成的CIL与普通类型没什么区别的。只是泛型的CIL是参数化的,可以接收在编码由用户提供类型。以下是两份经过编辑的CIL
4.1是普通类型编译过后的CIL
.class private stack extends [mscorlib] System.Object { }
4.2是泛型类型编译后的CIL.class private ‘stack‘1‘<([mscrolib]System.IComparable) T> extends [mscorlib] System.Object { .field private !0[ ] items }
从里面我们可以看出CIL用感叹号表示法来支持泛型,表明这里可以被外部传入的类型参数所替代。
泛型显著的改变了C#1.0的编码风格,虽然Java的JVM也支持泛型,但是在运行效率上面来说JVM不如C#