方法中Nullable泛型重载疑问:为何两种参数形式合法性不同?
C#泛型方法重载的差异解析
先看能正常编译的代码:
class A1 { public virtual T? F1<T>(T? t) where T : struct { throw new NotImplementedException(); } public virtual T? F1<T>(T? t) where T : class { throw new NotImplementedException(); } }
再看编译报错的代码:
class A1 { public virtual T? F1<T>(T t) where T : struct { throw new NotImplementedException(); } public virtual T? F1<T>(T t) where T : class { throw new NotImplementedException(); } }
错误提示:"Type 'A1' already defines a member called 'F1' with the same parameter types"
两者的核心差异在于参数是否为可空类型,原因如下:
第一个示例(参数为
T?):
当T受struct约束时,T?是Nullable<T>结构体,属于值类型;当T受class约束时,T?是可空引用类型,本质是带编译器注解的引用类型。这两种T?在C#类型系统中是完全不同的类型,编译器能明确区分两个方法的参数类型,因此允许重载。第二个示例(参数为
T):
C#的方法签名规则里,泛型约束不属于签名的一部分。这两个方法的签名都是F1<T>(T),仅约束不同,编译器不会把约束当作区分重载的依据。不管T是值类型还是引用类型,方法的参数列表在签名层面完全一致,所以编译器判定为重复定义,抛出错误。
简单来说:可空值类型是独立类型,能帮编译器区分重载;而泛型约束不参与签名判定,仅用T当参数时,两个方法的签名在编译器眼里完全一样。
内容的提问来源于stack exchange,提问作者Aliq Qim
相关产品推荐
相关产品推荐

