C# 泛型的类型约束
对于没有类型约束的泛型,其类型参数可以指定为任意类型。
例如List<T>,其类型参数T是值类型(List<int>)或引用类型(List<object>)。
有时候,我们希望泛型的类型参数只能是值类型或引用类型,这时就该论到类型约束上场了。
约束要放到泛型方法或泛型类型声明的末尾,并由关键字where来引入。
在C#中,有4中类型约束可供使用。
1、引用类型约束
这种约束用于确保使用的类型实参是应用类型。类型实参可以是任何类。接口。数组。委托,或者已知是引用类型的另外一个类型参数。例如以下声明:
class Sample<T> where T : class
Sample<object>、Sample<int[]>等引用类型作为类型实参的是有效的。
Sample<int>、Sample<Color>等值类型作为类型实参的无效的。
2、值类型约束
这种约束用于确保使用的类型实参是值类型的,包括枚举、结构体等,但可空类型除外。例如以下声明:
class Sample<T> where T : struct
Sample<int>、Sample<Color>等值类型作为类型实参的有效的。
Sample<object>、Sample<int[]>等引用类型作为类型实参的是无效的。
3、构造函数类型约束
构造函数类型约束表示为T:new(),如果有多个类型约束,必须是所有类型参数的最后一个约束。它检测类型实参是否有一个可用于类型实例的无参构造体。这适用于所有值类型;所有没有显式声明构造体的非静态类、非抽象类;所有显式声明了一个无参构造函数的非抽象类。实例如下:
public T Create<T>() where T : new() { return new T(); }
Create<int>()、Create<object>()都是有效的,但是Create<string>是无效的,因为string没有无参构造函数。
4、转换类型约束
最后一种类型约束允许你指定另一种类型,类型实参必须可以通过一致性、引用或装箱转换隐式地转换为该类型。一些例子如下:
class Sample<T> where T : Stream { }//有效:Sample<Stream>(一致性转换) //无效:Sample<string> class Sample<T> where T : IDisposable { }//有效:Sample<Stream>(引用转换) //无效:Sample<string> class Sample<T> where T : IComparable<T> { }//有效:Sample<int>(装箱转换) //无效:Sample<FileInfo> class Sample<T,U> where T : U { }//有效:Sample<Stream,IDisposable>(引用转换) //无效:Sample<string,IDisposable>