1. 程式人生 > >【C#】C#關鍵字-where(泛型型別約束)

【C#】C#關鍵字-where(泛型型別約束)

文章參考:http://blog.csdn.net/startwithdp/article/details/25636737
        http://www.cnblogs.com/soundcode/p/5798769.html
在定義泛型類時,可以對客戶端程式碼能夠在例項化類時用於型別引數的型別種類施加限制。如果客戶端程式碼嘗試使用某個約束所不允許的型別來例項化類,則會產生編譯時錯誤。這些限制稱為約束。約束是使用 where 上下文關鍵字指定的。下表列出了六種型別的約束:

約束
說明

T:結構
型別引數必須是值型別。可以指定除 Nullable 以外的任何值型別。有關更多資訊,請參見使用可以為 null 的型別(C# 程式設計指南)。

T:類
型別引數必須是引用型別;這一點也適用於任何類、介面、委託或陣列型別。

T:new()
型別引數必須具有無引數的公共建構函式。當與其他約束一起使用時,new() 約束必須最後指定。

T:<基類名>
型別引數必須是指定的基類或派生自指定的基類。

T:<介面名稱>
型別引數必須是指定的介面或實現指定的介面。可以指定多個介面約束。約束介面也可以是泛型的。

T:U
為 T 提供的型別引數必須是為 U 提供的引數或派生自為 U 提供的引數。這稱為裸型別約束

2.基類約束:指出某個型別必須將指定的類作為基類(或者就是該類本身),才能用作該泛型型別的型別引數。
 這樣的約束一經使用,就必須出現在該型別引數的所有其他約束之前。(也就是說:T必須是類。U必須是結構體,就是你傳的第一個泛型變數是類,第二個泛型變數是結構體)
class MyClassy<T, U>
 where T : class
 where U : struct
{
}
 3.where 子句還可以包括建構函式約束。
 可以使用 new 運算子建立型別引數的例項;但型別引數為此必須受建構函式約束 new() 的約束。new() 約束可以讓編譯器知道:提供的任何型別引數都必須具有可訪問的無引數(或預設)建構函式。例如:

public class MyGenericClass <T> where T: IComparable, new()
{
 // The following line is not possible without new() constraint:
 T item = new T();
}
new() 約束出現在 where 子句的最後。

 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 { }

請注意,對於委託和方法兩者來說,描述型別引數約束的語法是一樣的:


delegate T MyDelegate<T>() where T : new()