C#泛型default约束重写无约束方法的逻辑及用法示例咨询
C# 泛型default约束重写逻辑详解
背景
C# 8引入可空引用类型(NRT)后,泛型方法中的T?存在语义歧义:
- 当T为引用类型时,
T?表示允许为null的引用类型 - 当T为值类型时,
T?表示Nullable<T>类型
基类中如果存在无约束的泛型方法使用了T?,派生类重写时如果没有额外标识,编译器无法判断你要匹配的是无约束重载、还是带struct/class约束的重载,default约束就是用来解决这个匹配问题的。
完整代码示例
首先给出完整的基类实现:
public class B { // 无约束泛型方法:T可以是任意类型 public virtual void M<T>(T? item) { Console.WriteLine($"执行基类无约束方法,item值:{item ?? "null"}"); } // struct约束的重载:T只能是值类型 public virtual void M<T>(T? item) where T : struct { Console.WriteLine($"执行基类struct约束方法,item值:{item ?? "null"}"); } }
派生类重写无约束方法时必须加default约束:
public class D : B { // default约束明确告诉编译器:匹配基类无约束的泛型方法 public override void M<T>(T? item) where T : default { Console.WriteLine($"执行派生类重写方法,item值:{item ?? "null"}"); } }
不同T类型的调用验证
default约束下,T可以是任意类型,我们可以测试三种典型场景:
var d = new D(); // 场景1:T为引用类型string d.M<string>("测试文本"); // 输出:执行派生类重写方法,item值:测试文本 // 场景2:T为值类型int d.M<int>(100); // 输出:执行派生类重写方法,item值:100 // 场景3:T为可空值类型int? d.M<int?>(null); // 输出:执行派生类重写方法,item值:null
三种场景都能正常调用,符合基类无约束泛型方法的入参要求。
不加default约束的问题
如果去掉派生类方法的where T : default约束,编译器会默认将T?推导为值类型的Nullable<T>,自动匹配基类带where T : struct的重载,无法匹配我们要重写的无约束方法,甚至会因为签名不匹配抛出编译错误。
内容的提问来源于stack exchange,提问作者user1400915
相关产品推荐
相关产品推荐

