C#允許您使用約束來限制客戶端代碼在實例化泛型類型時指定某些類型。如果您嘗試使用指定約束不允許的類型實例化泛型類型,則會產(chǎn)生編譯時錯誤。
可以在泛型類型名稱后使用 where 子句在泛型類型上指定一個或多個約束。
GenericTypeName<T> where T : contraint1, constraint2
下面的示例演示了在實例化泛型類時具有對引用類型的約束的泛型類。
class DataStore<T> where T : class { public T Data { get; set; } }
上面,我們應用了類約束,這意味著在創(chuàng)建DataStore類對象時,只能將引用類型作為參數(shù)傳遞。因此,您可以傳遞引用類型,例如類,接口,委托或數(shù)組類型。傳遞值類型將產(chǎn)生編譯時錯誤,因此我們無法傳遞原始數(shù)據(jù)類型或結構類型。
DataStore<string> store = new DataStore<string>(); // 有效 DataStore<MyClass> store = new DataStore<MyClass>(); // 有效 DataStore<IMyInterface> store = new DataStore<IMyInterface>(); // 有效 DataStore<IEnumerable> store = new DataStore<IMyInterface>(); // 有效 DataStore<ArrayList> store = new DataStore<ArrayList>(); // 有效 //DataStore<int> store = new DataStore<int>(); // 編譯時錯誤
下表列出了泛型約束的類型。
約束 | 描述 |
---|---|
class | 類型參數(shù)必須是任何類、接口、委托或數(shù)組類型。 |
class? | 類型參數(shù)必須是可空或不可空的類、接口、委托或數(shù)組類型。 |
struct | 類型參數(shù)必須是非空值類型,如原始數(shù)據(jù)類型 int、 char、 bool、 float 等。 |
new() | 類型參數(shù)必須是具有公共無參數(shù)構造函數(shù)的引用類型。它不能與結構約束和非托管約束組合。 |
notnull | 從C# 8.0開始提供。類型參數(shù)可以是不可為null的引用類型或值類型。否則,編譯器將生成警告而不是錯誤。 |
unmanaged | 類型參數(shù)必須是不可空的非托管類型。 |
base class name | 類型參數(shù)必須是或派生自指定的基類。不允許將 Object、 Array、 ValueType 類作為基類約束。 在 c # 7.3之前,Enum,Delegate,MulticastDelegate 不允許作為基類約束。 |
<base class name>? | 類型參數(shù)必須是或派生自指定的可空或不可空的基類 |
<interface name> | 類型參數(shù)必須是或?qū)崿F(xiàn)指定的接口。 |
<interface name>? | 類型參數(shù)必須是或?qū)崿F(xiàn)指定的接口。它可以是可空引用類型、不可空引用類型或值類型 |
where T: U | 為 T 提供的類型參數(shù)必須是或派生自為 U 提供的參數(shù)。 |
下面的示例演示將類型參數(shù)限制為不可為null的值類型的struct約束。
class DataStore<T> where T : struct { public T Data { get; set; } } DataStore<int> store = new DataStore<int>(); // 有效 DataStore<char> store = new DataStore<char>(); // 有效 DataStore<MyStruct> store = new DataStore<MyStruct>(); // 有效 //DataStore<string> store = new DataStore<string>(); // 編譯時錯誤 //DataStore<IMyInterface> store = new DataStore<IMyInterface>(); // 編譯時錯誤 //DataStore<ArrayList> store = new DataStore<ArrayList>(); // 編譯時錯誤
下面的示例演示將類型參數(shù)限制為指定類、抽象類或接口的派生類的基類約束。
class DataStore<T> where T : IEnumerable { public T Data { get; set; } } DataStore<ArrayList> store = new DataStore<ArrayList>(); // 有效 DataStore<List> store = new DataStore<List>(); // 有效 //DataStore<string> store = new DataStore<string>(); // 編譯時錯誤 //DataStore<int> store = new DataStore<int>(); // 編譯時錯誤 //DataStore<IMyInterface> store = new DataStore<IMyInterface>(); // 編譯時錯誤 //DataStore<MyClass> store = new DataStore<MyClass>(); // 編譯時錯誤