在定義泛型類時,可以對用戶端代碼能夠在執行個體化類時用於型別參數的類型種類施加限制。如果用戶端代碼嘗試使用某個約束所不允許的類型來執行個體化類,則會產生編譯時間錯誤。這些限制稱為約束。約束是使用 where 內容關鍵字指定的。下表列出了五種類型的約束:
| 約束 |
說明 |
T:結構 |
型別參數必須是實值型別。可以指定除 Nullable 以外的任何實值型別。有關更多資訊,請參見使用可空類型(C# 編程指南)。 |
T:類 |
型別參數必須是參考型別,包括任何類、介面、委託或數群組類型。 |
T:new() |
型別參數必須具有無參數的公用建構函式。當與其他約束一起使用時,new() 約束必須最後指定。 |
T:<基類名> |
型別參數必須是指定的基類或派生自指定的基類。 |
T:<介面名稱> |
型別參數必須是指定的介面或實現指定的介面。可以指定多個介面約束。約束介面也可以是泛型的。 |
T:U |
為 T 提供的型別參數必須是為 U 提供的參數或派生自為 U 提供的參數。這稱為裸類型約束。 |
使用約束的原因
如果要檢查泛型列表中的某個項以確定它是否有效,或者將它與其他某個項進行比較,則編譯器必須在一定程度上保證它需要調用的運算子或方法將受到用戶端代碼可能指定的任何型別參數的支援。這種保證是通過對泛型類定義應用一個或多個約束獲得的。例如,基類約束告訴編譯器:僅此類型的對象或從此類型派生的對象才可用作型別參數。一旦編譯器有了這個保證,它就能夠允許在泛型類中調用該類型的方法。約束是使用內容關鍵字 where 應用的。
未綁定的型別參數
沒有約束的型別參數(如公用類 SampleClass<T>{} 中的 T)稱為未綁定的型別參數。未綁定的型別參數具有以下規則:
不能使用 != 和 == 運算子,因為無法保證具體型別參數能支援這些運算子。
可以在它們與 System.Object 之間來迴轉換,或將它們顯式轉換為任何介面類型。
可以將它們與 null 進行比較。將未綁定的參數與 null 進行比較時,如果型別參數為實值型別,則該比較將始終返回 false。
裸類型約束
用作約束的泛型型別參數稱為裸類型約束。當具有自己的型別參數的成員函數需要將該參數約束為包含類型的型別參數時,裸類型約束很有用。