泛型类的定义类似于一般的类,只是要使用泛型类型声明。之后就可以在类中把泛型类型用作成员字段,或方法的参数类型。在定义泛型类时,可以对客户端代码能够在实例化类时用于类型参数的类型种类施加限制。如果客户端代码尝试使用某个约束所不允许的类型来实例化类,则会产生编译时错误。这些限制称为约束。约束是使用 where 关键字指定的。
约束 | 说明 |
---|---|
T:结构 | 类型参数必须是值类型。可以指定除 Nullable 以外的任何值类型。 |
T:类 | 类型参数必须是引用类型;这一点也适用于任何类、接口、委托或数组类型。 |
T:new() | 类型参数必须具有无参数的公共构造函数。当与其他约束一起使用时,new() 约束必须最后指定。 |
T:<基类名> | 类型参数必须是指定的基类或派生自指定的基类。 |
T:<接口名称> | 类型参数必须是指定的接口或实现指定的接口。可以指定多个接口约束。约束接口也可以是泛型的。 |
T:U | 为 T 提供的类型参数必须是为 U 提供的参数或派生自为 U 提供的参数。这称为裸类型约束。 |
简单约束说明实例:
![ContractedBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
//值类型struct|引用类型class约束
public struct Text
{
}
public class Test<T>
where T : struct
{
//T在这里是一个值类型
}
public class Check
{
Test<Text> test = new Test<Text>();
}
//new()约束
public class Text
{
public Text() { }//无参数的构造函数
}
public class Test<T>
where T : new()
{
//可以在其中使用T t = new T();
}
public class Check
{
Test<Text> test = new Test<Text>();
}
//基类约束
public class Text
{
public void Add() { }
}
public class Test<T>
where T : Text//T继承至Text
{
//可以在类型为T的变量上调用Add()方法
}
//接口约束见下面实例
自定义泛型实例:
![ContractedBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
namespace Wrox.ProCSharp.Generics
{
using System;
using System.Threading;
using System.Collections.Generic;
public interface IDocument
{
string Title { get;}
string Content { get;}
}
public class Document : IDocument
{
private string title;
public string Title
{
get { return title; }
}
private string content;
public string Content
{
get { return content; }
}
public Document(string title, string content)
{
this.title = title;
this.content = content;
}
}
/// <summary>
/// 定制泛型类【使用接口约束】
/// </summary>
public class ProcessDocuments<TDocument, TDocumentManager>
where TDocument : IDocument
where TDocumentManager : IDocumentManager<TDocument>
{
public static void Start(TDocumentManager dm)
{
new Thread(new ProcessDocuments<TDocument, TDocumentManager>(dm).Run).Start();
}
protected ProcessDocuments(TDocumentManager dm)
{
//注意不能把null赋予泛型类型,因为泛型类型也可以是值类型。
//其中T doc = default(T);//则会将null赋予引用类型,把0赋予值类型。
documentManager = dm;
}
//使用泛型类型定义成员字段
private TDocumentManager documentManager;
protected void Run()
{
while (true)
{
if (documentManager.IsDocumentAvailable)
{
TDocument doc = documentManager.GetDocument();
Console.WriteLine("Processing document {0}", doc.Title);
}
Thread.Sleep(20);
}
}
}
/// <summary>
/// 定制泛型接口
/// </summary>
public interface IDocumentManager<T>
{
void AddDocument(T doc);
T GetDocument();
bool IsDocumentAvailable
{
get;
}
}
/// <summary>
/// 定制泛型类
/// </summary>
public class DocumentManager<T> : IDocumentManager<T>
{
private Queue<T> documentQueue = new Queue<T>();
//泛型类型作为参数类型
public void AddDocument(T doc)
{
lock (this)
{
documentQueue.Enqueue(doc);
}
}
//泛型类型作为返回类型
public T GetDocument()
{
T doc;
lock (this)
{
doc = documentQueue.Dequeue();
}
return doc;
}
public bool IsDocumentAvailable
{
get { return (documentQueue.Count > 0) ? true : false; }
}
}
class Program
{
static void Main(string[] args)
{
DocumentManager<Document> dm = new DocumentManager<Document>();
ProcessDocuments<Document, DocumentManager<Document>>.Start(dm);
for (int i = 0; i < 1000; i++)
{
Document doc = new Document("title" + i.ToString(), "content");
dm.AddDocument(doc);
Console.WriteLine("added document {0}", doc.Title);
Thread.Sleep(10);
}
}
}
}
原文地址:http://www.cnblogs.com/swollaws/archive/2009/05/12/1455115.html
【推荐】腾讯云新用户域名抢购1元起,抓紧抢购
· 今年CES无人驾驶汽车成主流:看看各大科技公司如何参与
· 阿里回应再入美国市场黑名单:政治化环境下的牺牲品
· 苹果电池告急 多家第三方推28美元更换服务
· 亚马逊专利战略曝光 聚焦视频、AR以及智能家居
· 摩拜发布共享单车与城市可持续发展报告:上海起最早、抗霾最积极
» 更多新闻...
· 以操作系统的角度述说线程与进程
· 软件测试转型之路
· 门内门外看招聘
· 大道至简,职场上做人做事做管理