C# 泛型约束
C# 允许您使用约束来限制客户端代码在实例化泛型类型时指定某些类型。如果您尝试使用指定约束不允许的类型实例化泛型类型,则会给出编译时错误。
您可以在泛型类型名称后使用 where
子句为泛型类型指定一个或多个约束。
语法
GenericTypeName<T> where T : contraint1, constraint2
以下示例演示了一个泛型类,该类在实例化泛型类时具有对引用类型的约束。
示例:声明泛型约束
class DataStore<T> where T : class
{
public T Data { get; set; }
}
上面,我们应用了类约束,这意味着在创建 DataStore 类对象时,只能将引用类型作为参数传递。因此,您可以传递引用类型,例如类、接口、委托或数组类型。传递值类型将导致编译时错误,因此我们不能传递原始数据类型或结构类型。
DataStore<string> store = new DataStore<string>(); // valid
DataStore<MyClass> store = new DataStore<MyClass>(); // valid
DataStore<IMyInterface> store = new DataStore<IMyInterface>(); // valid
DataStore<IEnumerable> store = new DataStore<IMyInterface>(); // valid
DataStore<ArrayList> store = new DataStore<ArrayList>(); // valid
//DataStore<int> store = new DataStore<int>(); // compile-time error
下表列出了泛型约束的类型。
约束 | 描述 |
---|---|
class | 类型参数必须是任何类、接口、委托或数组类型。 |
class? | 类型参数必须是可空或不可空的类、接口、委托或数组类型。 |
struct | 类型参数必须是不可空的值类型,例如原始数据类型 int、char、bool、float 等。 |
new() | 类型参数必须是具有公共无参构造函数的引用类型。它不能与 struct 和 unmanaged 约束结合使用。 |
notnull | C# 8.0 及更高版本可用。类型参数可以是不可空引用类型或值类型。如果不是,则编译器会生成警告而不是错误。 |
unmanaged | 类型参数必须是不可空的非托管类型。 |
基类名称 | 类型参数必须是指定的基类或派生自指定的基类。Object、Array、ValueType 类不允许作为基类约束。Enum、Delegate、MulticastDelegate 在 C# 7.3 之前不允许作为基类约束。 |
<base class name>? | 类型参数必须是指定的基类或派生自指定的基类(可空或不可空) |
<interface name> | 类型参数必须是指定的接口或实现指定的接口。 |
<interface name>? | 类型参数必须是指定的接口或实现指定的接口。它可以是可空引用类型、不可空引用类型或值类型 |
where T: U | 为 T 提供的类型参数必须是为 U 提供的参数或派生自该参数。 |
where T : struct
以下示例演示了 struct
约束,该约束将类型参数限制为仅不可空值类型。
示例:struct 约束
class DataStore<T> where T : struct
{
public T Data { get; set; }
}
DataStore<int> store = new DataStore<int>(); // valid
DataStore<char> store = new DataStore<char>(); // valid
DataStore<MyStruct> store = new DataStore<MyStruct>(); // valid
//DataStore<string> store = new DataStore<string>(); // compile-time error
//DataStore<IMyInterface> store = new DataStore<IMyInterface>(); // compile-time error
//DataStore<ArrayList> store = new DataStore<ArrayList>(); // compile-time error
where T : new()
以下示例演示了 struct
约束,该约束将类型参数限制为仅不可空值类型。
示例:new() 约束
class DataStore<T> where T : class, new()
{
public T Data { get; set; }
}
DataStore<MyClass> store = new DataStore<MyClass>(); // valid
DataStore<ArrayList> store = new DataStore<ArrayList>(); // valid
//DataStore<string> store = new DataStore<string>(); // compile-time error
//DataStore<int> store = new DataStore<int>(); // compile-time error
//DataStore<IMyInterface> store = new DataStore<IMyInterface>(); // compile-time error
where T : baseclass
以下示例演示了 base class
约束,该约束将类型参数限制为指定类、抽象类或接口的派生类。
示例:BaseClass 约束
class DataStore<T> where T : IEnumerable
{
public T Data { get; set; }
}
DataStore<ArrayList> store = new DataStore<ArrayList>(); // valid
DataStore<List> store = new DataStore<List>(); // valid
//DataStore<string> store = new DataStore<string>(); // compile-time error
//DataStore<int> store = new DataStore<int>(); // compile-time error
//DataStore<IMyInterface> store = new DataStore<IMyInterface>(); // compile-time error
//DataStore<MyClass> store = new DataStore<MyClass>(); // compile-time error