泛型约束(where子句)是编译期类型安全的关键机制,用于限定泛型参数可接受的类型,支持成员访问、实例化及协变/逆变等操作,共六类:class/struct、基类/接口、new()、in/out、组合约束及泛型参数约束。
泛型约束(where子句)不是可选项,而是让编译器在编译期就验证类型安全的关键机制。它限制了泛型参数能接受哪些具体类型,从而允许你在泛型代码中调用这些类型支持的操作——比如调用方法、访问属性、使用 new() 创建实例,或者进行特定的类型转换。
class / struct:限定引用类型或值类型
where T : class —— 确保 T 是类、接口、委托或数组(即非值类型),可用于判空或作为引用传递where T : s
truct —— 确保 T 是不可为 null 的值类型(不含 Nullable基类或接口约束:启用成员访问
where T : IComparable —— 可直接调用 CompareTo()
where T : Animal, ICloneable —— 支持多约束,T 必须继承 Animal 并实现 ICloneable构造函数约束:new()
where T : new() —— 要求 T 具有无参公共构造函数where T : class, new(),适用于工厂模式或 ORM 实体创建协变与逆变约束(仅适用于泛型接口/委托)
in T(逆变):T 仅作输入参数,如 IComparer,允许 IComparer 赋值给 IComparer
out T(协变):T 仅作返回值,如 IEnumerable,允许 IEnumerable 赋值给 IEnumerable
多个约束可用逗号分隔,顺序有要求:基类 → 接口 → new()
where T : Product, IValidatable, new()
where T : new(), IValidatable, Product(编译失败)泛型类型参数还可约束为另一个泛型参数:
class Container where T : class where U : T —— 表示 U 必须是 T 或其派生类约束只影响编译期检查,运行时仍可能遇到装箱/拆箱、null 引用或隐式转换问题
where T : class 不排除 nullable 引用类型(C# 8+ 默认开启 nullable reference types 后才可区分)where T : struct 排除了 Nullable(即 int?),因为它本质是泛型结构体,但编译器特殊处理,不能直接用在 struct 约束中IComparable.CompareTo 是否真正按预期比较),仍需运行时逻辑校验基本上就这些。合理使用 where 约束,能让泛型既保持通用性,又获得接近非泛型代码的类型提示和安全保证。