显而易见 类型约束的目的就是为了约束入参的参数类型
一共有四种约束可供使用,分别是引用类型约束,值类型约束,构造函数类型约束,转换类型约束
1、引用类型约束
确保类型实参是引用类型,表示成 T : Class,且必须是类型参数指定的第一个约束(可能会有多个约束)。类型实参任何类、接口、数组、委托、或者已知识引用类型的另一个类型实参:
//约束类
public class TypeConstraintDemo
{
/// <summary>
/// 引用类型约束实例
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="entity"></param>
public void SaveStudentInfo<T>(T entity) where T : class
{
//TODO 逻辑
}
}
//引用类型约束实例
TypeConstraintDemo typeConstraintDemo = new TypeConstraintDemo();
Student stu = new Student();
stu.id = 1;
stu.name = "Jack";
stu.age = 13;
typeConstraintDemo.SaveStudentInfo<Student>(stu);
2、值类型约束
表示成 T : struct,确保类型实参是值类型,不包括可空类型
/// <summary>
/// 值类型约束实例
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="entity"></param>
public Student GetStudentById<T>(T entity) where T : struct
{
//TODO 逻辑
return new Student();
}
//值类型约束调用
typeConstraintDemo.GetStudentById<int>(1);
3、构造函数类型约束
表示成 T : new(),必须是所有类型参数的最后一个参数,它检查类型实参是否有一个可用于创建类型参数的无参构造函数
适用于以下三种情况:
1)所有值类型
2)所有没有显式声明构造函数的非静态、非抽象类
3)所有显式声明了一个公共午餐构造函数的非抽象类
public T CreateInstance<T>() where T : new()
{
return new T();
}
//报错,因为string 没有一个无参的构造方法
typeConstraintDemo.CreateInstance<string>();
//正确
typeConstraintDemo.CreateInstance<Student>();
//正确
typeConstraintDemo.CreateInstance<int>();
4、转换类型约束
允许指定另一个类型,类型实参必须可以通过一致性、引用或者装箱转换隐式地转换为该类型。
还可以规定一个类型实参必须可以转换为另一个类型实参
实例
声明 | 例子 |
class Sample<T> Where T : Stream | 有效: Sample<Stream> (自一致性转换) 无效:Sample<string> |
struct Sample <T> where T : IDisposable | 有效:Sample<SqlConnection>(引用转换) 无效:Sample<StringBuilder> |
class Sample<T> where T :IComparable<T> | 有效:Sample<int> (装箱转换) 无效:Sample<FileInfo> |
class Sample<T,U> where T :U | 有效:Sample<Stream,IDisposable>(引用转换) 无效:Sample<string,IDisposable> |
可以指定多个接口,但是只能指定一个类
class Sample<T> where T : Stream,IEnumerable<string>,IComparable<int>
指定的类不可以是结构、密封类或者System.Object、System.Enum、System.ValueType和System.Delegate中任意一个。
5、组合约束
将不同种类的约束合并到一起。
不同类型参数可以有不同的约束,它们分别由一个单独的where引入
下面是一些无效的组合约束及其解释
//不可以同时是引用类型和值类型
class Sample<T> where T : class, struct
//不可以同时是值类型和引用类型
class Sample<T> where T : struct, class
//Stream没有无参的构造函数且new()必须是最后一个约束
class Sample<T> where T : new(), Stream
//IDisposable在Stream后面
class Sample<T> where T : IDisposable, Stream
//不可以同时添加两个一样的约束
class Sample<T> where T : xmlReader, IComparable, IComparable
//U不可以同时是引用类型约束和值类型约束
class Sample<T> where T : struct where U : class, T
//每个约束都必须使用单独的wehere ,U 应该有单独的where
class Sample<T> where T : Stream, U : IDisposable