---------------------- Windows Phone 7手机开发、.Net培训、期待与您交流! ----------------------
什么是泛型?
泛型是.NET 2.0引入的一个概念。泛型不仅是C#语言的一部分,而且与程序集中的IL代码紧密继承。有了泛型 我们就可以创建于独立于被包含类的类和方法了。
泛型不仅是C#的语言结构,而且还是由CLR定义的。那么既然是CLR定义的,那么只要是支持CLR的语言就都支持泛型,于是我们很快就能联想到VB.NET。
为什么要有泛型?
首先第一点:性能
在.NET中数据类型分为值类型和引用类型。从值类型到引用类型的转换 我们称之为装箱,从引用类型到值类型的转换 我们称之为装箱。
装箱和拆箱会消耗很多资源。特变是在遍历一个集合的时候。
一般的值类型对象和引用类型对象之间的转换工作会涉及到装箱和拆箱,这种过程对系统开销是比较大的。 泛型类不需要装箱拆箱的操作。因为(这里是书上的原话):泛型类不使用对象,而是在使用时定义类型,比如List
个人对这段话的理解:泛型类型 和一般类型不一样,一般类型之间的转换是由.Net提供的默认的装箱和拆箱的操作,这个工程是普遍的。优点是 可以对不同数据类型的数据都执行这种操作,缺点是开销大,效率低。
而泛型 是会根据 你定义了泛型类型,此类型会在JIT中及时编译成一个动态类,它不需要数据转化,无需装箱拆箱的操作,所以就没有必要调用.NET提供的默认的装箱拆箱的运算。 优点是 效率提高了,缺点是没有普遍使用性。因为 泛型数据类型已经确定了。
第二点:安全性
泛型中定义了允许使用的类型,是使用泛型处理该数据时,如果数据类型不对,编译器就会给出错误提示。
比如说 var list = new list
list.Add("我");//编译器不会让你通过,
foreach( int i in list)
{
//遍历不涉及装箱拆箱的操作提高系统效率
}
第三点:代码重用
泛型可以更好的重用二进制代码.泛型类型可以定义一次,就可以用于许多不同类型的数据类型的实例化。
例子:var list = new list
var list = new list
我对这个例子是这么理解的:因为所有的代码会通过编译器编程成微软中间语言IL CLR又会将微软中间语言编译成平台能识别的机器码,机器码是不是1100100这样的二进制 我不知道,但是代码最终就编译成1010010这样的代码 。
上述的例子中 new list
泛型约束:
where T:Struct 泛型类型T必须是值类型
where T:class 泛型类型T必须是引用类型
where T:IFoo 泛型T必须实现IFoo接口
where T:Foo 泛型T必须继承是类Foo
where T:new() 指定的类型T必须包含一个不带参数的构造函数
where T1;T2 泛型类型T1派生自泛型类型T2 此类型约束也称之为“裸约束”
下面我们就为where T:IFoo 泛型类型必须实现某个接口 来敲一个例子。
创建一个DocumentManager类 用来管理文档信息,不过不是传统的DocumentManager而是泛型的DocumentManager
public class DocumentManager<TDocument> where TDocument:IDocument { private readonly Queue<T> documentQue = new Queue<T>();//文档数据队列 //将T数据类型文档添加到当前队列 public void AddDocument<T>(T doc) { lock(this) { documentQue.Enqueue(doc); } } //返回当前队列是否有文档。 public bool IsDocumentAvailable { get{return documentQue.Length>0;} } public T GetDocument() { //defalut关键字 给值类型赋0,引用类型赋null T doc = default(T); lock(this) { doc = documentQue.Dequeue(); } return doc; } //显示所有的文档通过上述约束可以将T转化为IDocument类型 public void DisplayAllDoucment() { foreach(T doc in documentQue) { IDocument Id = doc; Console.WriteLine(Id.Title); Console.WriteLine(Id.Content); } } } //现在在对应一个IDocument的接口 来确定Document数据类型必须包含的信息 public interface IDocument { string Title{get;set;} string Content{get;set;} } //定义一个Document的类来实现IDocument接口 public class Document:IDocument { //属性自动实现(不清楚见学习笔记1) public string Title{get;set;} public string Content{get;set;} public Document(string title,string content) { this.Title = title; this.Content= content; } } 然后 我们在前台:
var dm = new DocumentManager<Document>();//Document实现了IDocument 才能作为DocumentManager的泛型类型
dm.AddDocument(new Document("Asp.Net自定义控件开发","野战鹰"));
dm.AddDocuemt(new Document("C#高级编程第七版","Wrox"));
dm.DisplayAllDocument();
//我们在此方法中 又将每一个传入进去的Document对象转化为了IDocument接口类型。
if(dm.IsDocumentAvailable)
{<!-- -->
IDocument Id = dm.GetDocument();
Console.WriteLine(Id.Content);
}
泛型继承:
泛型类型可以继承实现泛型接口,也可以派生自泛型类.
当泛型类型派生自泛型类时:它必须满足下面两个条件之一:
其一:必须重复基类的泛型类型;
其二:在基类中为其指定泛型数据类型;
例子:
基类泛型 Base
必须是: Derived
于是派生类可以使泛型也可以是非泛型(条件二:Base已经为派生类指定了需要处理的数据类型)
泛型静态成员:泛型静态成员只能在类的一个实例中共享。
eg:
public class StaticDemo
{
public static int x;
}
StaticDemo
StaticDemo
Console.WriteLine(StaticDemo
泛型接口
一般老的接口比如
Interface IComparable
{
//参数类型一般都为object 原因是微软不知道具体要实现的这个类类中对该方法的实现
//要传递一个什么样类型的参数。
int CompareTo(object obj);
}
所以每次实现起来 都会有一个装箱的操作。
public class Person:IComparable
{
public int CompareTo(object obj)
{
Person other = obj as Person;//装箱
if(condition)
{
//内部逻辑
}
}
}
但是 如果我们顶一个泛型接口的话,就可以省掉这么一个装箱的操作了。
Interface IComparable
{
int CompareTo(T t);
}
public class Person:IComparable
{
public int compareTo(Person p)
{
if(conditon)
{
//...逻辑......
}
}
}
泛型方法:
也可以把方法定义成泛型的
void Swap
{
Console.WriteLine*(t1+t2).ToString());
}
调用时可以
Swap
也可以
Swap(ref 1,ref 2);
编译器会根据参数类型来推断T的类型。
---------------------- Windows Phone 7手机开发、 .Net培训、期待与您交流! ----------------------