详解c# 泛型类的功能
在泛型类中,由于不知道泛型参数T是什么类型,可能是引用类型,也可能是值类型,因此不能将null等赋予泛型类型。如何对泛型对象赋初值、如何保证泛型的正确性等,以使用泛型文档管理器为例:
文档管理器用于从队列中读写文档。首先创建一个泛型管理器AddDocument()方法添加一个文档到队列中,IsDocumentAvailabe只读属性指示队列中是否还有文档。
publicclassDocumentManager{ privatereadonlyQueue documentQueue=newQueue (); publicvoidAddDocument(Tdoc) { lock(this) { documentQueue.Enqueue(doc); } } publicboolIsDocumentAvailable { get{returndocumentQueue.Count>0;} } }
1、默认值
给DocumentManager
publicTGetDocument() { Tdoc=default(T); lock(this) { if(documentQueue.Count>0) { doc=documentQueue.Dequeue(); } } returndoc; }
2、约束
如果泛型类需要调用泛型类型中的方法,那么必须对泛型添加约束。否则,不能确保声明的泛型类型实现了对应的类型,具有相关方法。创建文档类Document,其实现了接口IDocument:
publicinterfaceIDocument { stringTitle{get;set;} stringContent{get;set;} } publicclassDocument:IDocument { publicDocument() { } publicDocument(stringtitle,stringcontent) { this.Title=title; this.Content=content; } publicstringTitle{get;set;} publicstringContent{get;set;} }
给泛型文档管理器DocumentManager
publicvoidDisplayAllDocuments() { foreach(TdocindocumentQueue) { Console.WriteLine((docasIDocument).Title);//强制转换 } }
但是,如果类型T没有实现接口IDocument,在对类型进行强制转换时就会出现一个异常。如果对方法添加rty……catch处理,将非常损耗性能。同样的,即使类型实现了接口IDocument,在进行转换时也会出现性能的损耗。
那么,如果能对泛型TDocument进行约束,使得泛型类型必须实现接口IDocument,则不会出现对类型进行强制转换时的异常。甚至不需要强制转换,性能也将得到优化。因此,前面的泛型文档管理器改写为(前面的T,改写为TDocument,以此暗示是文档类型):
publicclassDocumentManagerwhereTDocument:IDocument { //…… }
对于实现了约束的泛型文档管理器,可以处理任何实现了IDocument接口的类。其DisplayAllDocuments()方法改写为:
publicvoidDisplayAllDocuments() { foreach(TDocumentdocindocumentQueue) { Console.WriteLine(doc.Title); } }
在其他地方调用时,可以用Document类型实例化泛型类型DocumentManager
staticvoidMain() { vardm=newDocumentManager(); dm.AddDocument(newDocument("TitleA","SampleA")); dm.AddDocument(newDocument("TitleB","SampleB")); dm.DisplayAllDocuments(); if(dm.IsDocumentAvailable) { Documentd=dm.GetDocument(); Console.WriteLine(d.Content); } }
泛型类型支持的几种约束:struct(结构约束,类型T必须是值类型)、class(类约束,类型T必须是引用类型)、IFoo(类型T必须实现接口IFoo)、new()(构造函数约束,类型T必须有一个无参构造函数)、TOther(类型T派生自TOther,也称“裸类型约束”)。
泛型约束中:
- 只能为无参构造函数定义构造约束,不能为有任何参数的构造函数定义构造函数约束。
- 泛型可以有多个约束。如:publicclassDocumentManager
whereTDocument:IDocument,new()。 - where不能定义必须由泛型类型实现的运算符
3、继承
泛型类也可以实现继承,如Queue
classBase{ //............... } classDerived :Base { //............... }
派生类可以是泛型类,也可以是非泛型类型:
abstractclassCalc{ publicabstractTAdd(Tx,Ty); publicabstractTSub(Tx,Ty); } classIncCalc:Calc { publicoverrideintAdd(intx,inty) { returnx+y; } publicoverrideintSub(intx,inty) { returnx-y; } } classDoubleCalc:Calc { publicoverridedoubleAdd(doublex,doubley) { returnx+y; } publicoverridedoubleSub(doublex,doubley) { returnx-y; } }
4、静态成员
泛型类的静态成员只能在一个实例中共享:
classStaticDemo{ publicstaticstringType; } staticvoidMain() { StaticDemo .Type="int类型"; StaticDemo
实际上,每当用一个类型去代替泛型中的T时,都是在创造一个实例类型。因此,泛型类型中的静态字段,会在不同的类型替代泛型T的实例中重新生成。这样设计也有好处,可以为程序提供一个“泛型缓存”的概念,使用泛型的静态成员,使它存放在缓存中,方便调用。
以上就是详解c#泛型类的功能的详细内容,更多关于c#泛型类的资料请关注毛票票其它相关文章!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。