generics的扩展方法

我正在看这个问题,我很好奇为什么这个不能编译。

鉴于此代码,任何人都可以解释为什么对IBase.Test()的调用没有解析为正确的扩展方法?

 public interface IBase { } public interface IChildA : IBase { } public interface IChildB : IBase { } public static class BaseExtensions { public static IBase Test(this IBase self) { return self; } public static T Test(this T self) where T : IChildB { return self; } } public static class TestClass { public static void Test() { IChildA a = null; //Yeh i know its null but just testing for compile here.. IBase firstTry = a.Test(); //Cannot resolve to BaseExtensions.Test(this IBase obj) IBase secondTry = ((IBase)a).Test(); //Resolves to BaseExtensions.Test(this IBase obj) IChildB b = null; IChildB touchedB = b.Test(); } } 

我得到的错误是

Error 166 The type 'IChildA' cannot be used as type parameter 'T' in the generic type or method 'BaseExtensions.Test(T)'. There is no implicit reference conversion from 'IChildA' to 'IChildB'.

我有一种感觉,因为对于任何实现IChildB并且不知道使用哪种扩展方法的东西来说它会很暧昧,但是错误消息不会对它的那一边IBase firstTry = a.Test(); ,如果你删除了IBase firstTry = a.Test(); 然后它编译好..

好的,问题是在重载解析过程中,编译器会查找所有适用的候选方法, 而不检查方法中指定的generics约束,选择最具体的约束, 然后检查generics约束。

在这种情况下,generics方法比非generics方法更具体(因为在类型参数替换之后,它实际上是一个带有IChildA参数而不是IBase参数的方法) – 但它然后失败了约束。

我有一篇博文更详细地解释了这一点,另一篇以可怕的方式使用它 。