六種類型的約束:
T:結構 |
類型參數必須是值類型。可以指定除 Nullable 以外的任何值類型。有關更多信息,請參見使用可空類型(C# 編程指南)。 |
T:類 |
類型參數必須是引用類型,包括任何類、接口、委托或數組類型。 |
T:new() |
類型參數必須具有無參數的公共構造函數。當與其他約束一起使用時,new() 約束必須最后指定。 |
T:<基類名> |
類型參數必須是指定的基類或派生自指定的基類。 |
T:<接口名稱> |
類型參數必須是指定的接口或實現指定的接口。可以指定多個接口約束。約束接口也可以是泛型的。 |
T:U |
為 T 提供的類型參數必須是為 U 提供的參數或派生自為 U 提供的參數。這稱為裸類型約束。 |
例子:
1.接口約束。
例如,可以聲明一個泛型類 MyGenericClass,這樣,類型參數 T 就可以實現 IComparable<T> 接口:
public class MyGenericClass<T> where T:IComparable { }
2.基類約束。
指出某個類型必須將指定的類作為基類(或者就是該類本身),才能用作該泛型類型的類型參數。這樣的約束一經使用,就必須出現在該類型參數的所有其他約束之前。
class MyClassy<T, U> where T : class where U : struct { }
3.構造函數約束。
以使用 new 運算符創建類型參數的實例;但類型參數為此必須受構造函數約束 new() 的約束。new() 約束可以讓編譯器知道:提供的任何類型參數都必須具有可訪問的無參數(或默認)構造函數。new() 約束出現在 where 子句的最后。
public class MyGenericClass <T> where T: IComparable, new() { // The following line is not possible without new() constraint: T item = new T(); }
4.對於多個類型參數,每個類型參數都使用一個 where 子句。
interface MyI { } class Dictionary<TKey,TVal> where TKey: IComparable, IEnumerable where TVal: MyI { public void Add(TKey key, TVal val) { } }
5.還可以將約束附加到泛型方法的類型參數。
public bool MyMethod<T>(T t) where T : IMyInterface { }
6. 裸類型約束
用作約束的泛型類型參數稱為裸類型約束。當具有自己的類型參數的成員函數需要將該參數約束為包含類型的類型參數時,裸類型約束很有用。
class List<T> { void Add<U>(List<U> items) where U : T {/*...*/} }
泛型類的裸類型約束的作用非常有限,因為編譯器除了假設某個裸類型約束派生自 System.Object 以外,不會做其他任何假設。在希望強制兩個類型參數之間的繼承關系的情況下,可對泛型類使用裸類型約束。
7.default關鍵字
之所以會用到default關鍵字,是因為需要在不知道類型參數為值類型還是引用類型的情況下,為對象實例賦初值。考慮以下代碼:
class TestDefault<T> { public T foo() { T t = null; //??? return t; } }
如果我們用int型來綁定泛型參數,那么T就是int型,那么注釋的那一行就變成了 int t = null;顯然這是無意義的。為了解決這一問題,引入了default關鍵字:
class TestDefault<T> { public T foo() { return default(T); } }
參考:http://www.jb51.net/article/37658.htm
http://www.cnblogs.com/ottox/archive/2009/03/02/1401307.html
http://www.jb51.net/article/41143.htm