在C#编程中,类型参数约束用于在声明泛型类、方法、委托或接口时,对类型参数做出限制,确保客户端代码传递给泛型类型的类型参数满足特定条件。类型参数约束让编译器知道类型参数必须具备什么样的功能,这样编译器就可以安全地在泛型代码内部调用那些依赖于特定条件的方法或属性。
以下是C#中支持的主要类型参数约束:
1.类约束(class)
where T : class
这表明类型参数 T
必须是一个引用类型(包括任何类或接口,但不包括值类型)。
2.值类型约束(struct)
where T : struct
这意味着类型参数 T
必须是一个不可为null的值类型。所有的值类型都有默认的无参构造函数,所以这也隐含了 new()
约束,因此不能同时显式指定 new()
和 struct
约束。
3.new()约束
where T : new()
表明类型参数 T
必须有一个无参的公共构造函数,这意味着任何传入的类型都可以通过 new T()
创建实例。
4.接口约束
where T : IComparable
或者同时指定多个接口:
where T : ISerializable, IComparable<T>
这要求类型参数 T
必须实现指定的接口。
5.基类约束
where T : MyBaseClass
要求类型参数 T
必须是从指定基类派生的类型。
6.可空约束(C# 8.0及以后版本)
where T : notnull
表示类型参数 T
不允许为null,适用于引用类型。
7.非托管约束(C# 7.3及以后版本)
where T : unmanaged
要求类型参数 T
是一个非托管类型,即值类型并且由编译器控制的内存管理,如整数、浮点数、指针类型等。
约束在泛型声明中使用 where
关键字来指定,例如:
public class MyClass<T> where T : IEquatable<T>, new()
{
public T CreateInstance() => new T();
public bool IsEqualTo(T other) => other?.Equals(default(T)) ?? false;
}
在这个例子中,类型参数 T
需要实现 IEquatable<T>
接口,并且必须有一个无参的公共构造函数。这样在类的内部就可以安全地创建 T
类型的新实例,并使用 Equals
方法进行比较。