泛型种类:
1)泛型类
2)泛型接口
3)泛型方法
4)泛型数组
5)泛型委托
6)泛型结构
泛型约束:
为什么要使用泛型约束?
通过约束类型参数,可以增加约束类型及其继承层次结构中的所有类型所支持的允许操作和方法调用的数量。设计泛型类或方法时,如果要对泛型成员执行除简单赋值之外的任何操作或调用System.Object不支持的任何方法,则必须对该类型参数应用约束。例如,基类约束告诉编译器,仅此类型的对象或派生自此类型的对象可用作类型参数。编译器有了此保证后,就能够允许在泛型类中调用该类型的方法。
泛型约束的类型:
1)where T : struct => 类型参数必须是值类型。可以指定除Nullable<T>以外的任何值类型。
2)where T : class => 类型参数必须是引用类型。此约束还应用于任何类、接口、委托或数组类型。
3)where T : notnull => 类型参数必须是不可为null的类型。(C#8.0开始)
4)where T : unmanaged => 类型参数必须是非托管类型。
5)where T : new() => 类型参数必须具有公共无参数构造函数。
6)where T : <基类名> => 类型参数必须是指定的基类或派生自指定的基类。
7)where T : <接口名称> => 类型参数必须是指定的接口或实现指定的接口。可指定多个接口约束。约束接口也可以是泛型。
8)where T : U => 为 T 提供的类型参数必须是为U提供的参数或派生自为U提供的参数。
使用泛型约束的细节:
1)与其他约束一起使用时,new()约束必须最后指定。
2)class或struct约束必须再其他任何约束之前。
3)struct约束包含new()约束,且new()约束不能与struct约束结合使用。
4)unmanaged约束包含struct约束,unmanaged约束不能与struct或new()约束结合使用
泛型约束的使用类型:
1)泛型约束可以是一个泛型类型参数对应一个约束,或多个约束
2)泛型约束也可以是多个泛型参数对应多个约束
未绑定约束的类型参数有哪些特点:
1)不能使用 != 和 == 运算符,因为无法保证具体的类型参数能支持这些运算符。
2)可以在它们与System.Object之间来回转换,或将它们显式转换为任何接口类型。
3)可以将它们与null进行比较。将未绑定的参数与null进行比较时,如果类型参数为值类型,则该比较将始终返回false。
【注:】
1)从C#7.3开始,可使用unmanaged约束来指定类型参数必须为非托管类型。
2)从C#7.3开始,可将 System.Delegate 或 System.MulticastDelegate 或 System.Enum 用作基类约束。CLR始终允许此约束,但 C# 语言不允许。