C#学习之泛型功能与限制

在泛型类的描述中还会有时需要很多限制,例如对待一个泛型类型,在类中定义一个变量需要初始化时,不能确定是用Null还是0.

因为不能够确定它是值类型还是引用类型,这时可以用到default语句(下面有介绍)。

下面的是一个文档管理器的详细代码和必要详细的解释。

  1 //定义一个具有内容和标题属性的接口
  2 
  3 namespace Function
  4 {
  5     public interface IDocument
  6     {
  7         string Content { set; get; }
  8         string Title { set; get; }
  9     }
 10 }
 11 //下面是文档类型的具体描述,它继承了上面的接口
 12 namespace Function
 13 {
 14     public class Document:IDocument
 15     {
 16         public Document()
 17         {
 18 
 19         }
 20         public Document(string title,string content)
 21         {
 22             this.Title = title;
 23             this.Content = content;
 24         }
 25         public string Title
 26         {
 27             get;
 28             set;
 29         }
 30         public string Content
 31         {
 32             get;
 33             set;
 34         }
 35     }
 36 }
 37 
 38 //下面是文档管理器类的具体描述
 39 namespace Function
 40 {
 41     //下面类中的where 子句的作用是要求
 42     //本泛型类的T的具体类型必须是继承IDcoument接口的。
 43     //如果T类型不是继承IDcoument接口,那么就不能应用到本泛型类
 44     //这里的DocumentManager<T>可以实现任何继承了接口IDcoument的类型
 45     //where子句还有很多其他的意义,可以看最后的图片介绍
 46     public class DocumentManager<T> where T : IDocument
 47     {
 48         private readonly Queue<T>documentQueue=new Queue<T>();
 49         public void AddDocument(T doc)
 50         {
 51             //Lock语句的通俗点的意思是当有一个函数在调用本模块时,其他的函数就不能再次调用
 52             //等到这里执行完毕后再被其他的使用
 53            lock(this)
 54             {
 55                 documentQueue.Enqueue(doc);
 56             }
 57         }
 58         public bool IsDocumentAvailable()
 59         {
 60             return (documentQueue.Count > 0);
 61         }
 62         public T GetDocument()
 63         {
 64             T doc = default(T);//定义doc变量,并赋予初值
 65             //但是因为此处的T类型并不明确是引用类型还是值类型,
 66             //赋初值时就不能明确赋予Null还是0
 67             //default(T)可以根据类型自动赋值
 68             lock(this)
 69             {
 70                 doc = documentQueue.Dequeue();
 71             }
 72             return doc;
 73         }
 74         public void DisplayAllDocuments()
 75         {
 76             foreach(T doc in documentQueue)
 77             {
 78                 Console.WriteLine(doc.Title);
 79             }
 80         }
 81     
 82     }
 83 }
 84 //下面是主函数
 85 using System;
 86 using System.Collections.Generic;
 87 using System.Linq;
 88 using System.Text;
 89 using System.Threading.Tasks;
 90 
 91 namespace Function
 92 {
 93     class Program
 94     {
 95         static void Main(string[] args)
 96         {
 97 //实例化文档管理器类,并且赋值,然后取出其中的值
 98             var dm = new DocumentManager<Document>();
 99             dm.AddDocument(new Document("name1","content1"));
100             dm.AddDocument(new Document("name2", "content2"));
101             dm.AddDocument(new Document("name3", "content3"));
102             dm.DisplayAllDocuments();
103             while(dm.IsDocumentAvailable())
104             {
105                 Document doc = null;
106                 doc = dm.GetDocument();
107                 Console.WriteLine(doc.Content+" "+doc.Title);
108             }
109             Console.ReadKey();
110             return;
111         }
112 
113     }
114 }

下面是where子句的详细介绍,也可以参看http://msdn.microsoft.com/zh-cn/library/bb384067.aspx。有详细而专业的介绍。

约束语句说明
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 子句只能为默认构造函数定义构造函数约束,不能为其他构造函数定义构造函数约束。

使用泛型类还可以合并多个约束。例如where T:IFoo,new().其意义就是说T必须继承实现IFoo接口也要有默认构造函数

在where语句中只能定义基类,接口和默认构造函数