在定義泛型類時,可以對客戶端代碼能夠在實例化類時用於類型參數的類型種類施加限制。如果客戶端代碼嘗試使用某個約束所不允許的類型來實例化類,則會產生編譯時錯誤。這些限制稱為約束。約束是使用 where 上下文關鍵字指定的。
下面列出了六種類型的約束:
約束說明
T:結構
類型參數必須是值類型。可以指定除 Nullable 以外的任何值類型。有關更多信息,請參見使用可空類型(C# 編程指南)。
T:類
類型參數必須是引用類型,包括任何類、接口、委托或數組類型。
T:new()
類型參數必須具有無參數的公共構造函數。當與其他約束一起使用時,new() 約束必須最后指定。
T:<基類名>
類型參數必須是指定的基類或派生自指定的基類。
T:<接口名稱>
類型參數必須是指定的接口或實現指定的接口。可以指定多個接口約束。約束接口也可以是泛型的。
T:U
為 T 提供的類型參數必須是為 U 提供的參數或派生自為 U 提供的參數。這稱為裸類型約束。
使用約束的原因:
如果要檢查泛型列表中的某個項以確定它是否有效,或者將它與其他某個項進行比較,則編譯器必須在一定程度上保證它需要調用的運算符或方法將受到客戶端代碼可能指定的任何類型參數的支持。這種保證是通過對泛型類定義應用一個或多個約束獲得的。例如,基類約束告訴編譯器:僅此類型的對象或從此類型派生的對象才可用作類型參數。一旦編譯器有了這個保證,它就能夠允許在泛型類中調用該類型的方法。約束是使用上下文關鍵字 where 應用的。
泛型約束基本上有五種:
值類型約束:要求泛型參數必須是值類型,例如int,short以及自定義的stuct等
public class MyClass2<T>
where T : struct//這個泛型類只接受值類型的泛型參數
{
}
引用類型約束:要求泛型參數必須是引用類型,例如string,object,以及自定義的class
public class MyClass<T>
where T:class//這個泛型類只接受引用類型的泛型參數
{
}
構造函數約束:要求泛型參數必須有構造函數
public class MyClass3<T>
where T : new()
{
}
接口約束:要求泛型參數必須實現某個接口
public class MyClass4<T>
where T : System.IComparable
{
}
基類約束:要求泛型參數必須繼承某個基類
public class MyClass5<T>
where T : Customer
{
}