具有泛型的扩展方法

时间:2011-03-23 09:50:58

标签: c# .net generics extension-methods

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

鉴于此代码,有人可以解释为什么对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<T>(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>(T)'. There is no implicit reference conversion from 'IChildA' to 'IChildB'.

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

1 个答案:

答案 0 :(得分:5)

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

在这种情况下,泛型方法比非泛型方法更具体(因为在类型参数替换之后,它实际上是一个带有IChildA参数而不是IBase参数的方法) - 但是然后它没有达到约束条件。

我有一个blog post更详细地解释了这一点,另一个using it in a horrible way