这不应该是有效的C#代码吗?
class A<T> where T : class {
public void DoWork<K>() where K : T {
var b = new B<K>(); // <- compile time error
}
}
class B<U> where U : class {
}
Run Code Online (Sandbox Code Playgroud)
编译器吐出此错误:
错误CS0452:类型"K"必须是引用类型,以便在泛型类型或方法"ConsoleApplication1.B"中将其用作参数"U"
编译器是否应该能够确定K是约束为T类型还是从T派生,因此它显然应该是引用类型(T被约束为引用类型)?
我之前的回答不正确; 我删除了它.感谢用户配置器指出我的错误.
编译器是否应该能够确定K是约束为T类型还是从T派生,因此它显然应该是引用类型(T被约束为引用类型)?
没有.
K被约束为T型或从T派生的类型.T被约束为参考类型. 这并不意味着K是参考类型. Viz:object是引用类型,int是从object派生的类型.如果T是对象,则K可以是int,这不是引用类型.
指定type参数时将应用约束.虽然为U指定了K,但尚未为K指定类型.由于U要求其类型为引用类型,因此编译器希望确认K确实是引用类型,但它不能.因此,您需要明确说明它将是.
规范在4.4.4节中说明:
对于每个where子句,将针对每个约束检查与命名的类型参数对应的类型参数A.
然后:
如果给定类型参数不满足一个或多个类型参数的约束,则会发生编译时错误.
由于不继承类型参数,因此也不会继承约束.
最后一点表明K不会继承T的约束.
更新
虽然我的结论看起来是正确的,但我的证据有点不稳定,正如Eric Lippert的回复中现在删除的回复中所阐明的那样.在那里,Eric表示规范的正确部分是:
如果类型参数具有引用类型约束或其有效基类不是对象或类型,则已知该类型参数是引用类型
System.ValueType.