扩展方法与仿制药方法

由网友(你的名字再不是我的心事)分享简介:我在看this的问题,我很好奇,为什么这deosn't编译。I was looking at this question and i was curious why this deosn't compile.鉴于这种code,任何人都可以解释为什么在调用 IBase.Test()不能解决正确的扩展方法?Given...

我在看this的问题,我很好奇,为什么这deosn't编译。

I was looking at this question and i was curious why this deosn't compile.

鉴于这种code,任何人都可以解释为什么在调用 IBase.Test()不能解决正确的扩展方法?

Given this code, can anyone explain why the call to IBase.Test() doesn't resolve to the correct extension method?

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();
    }
}

我得到的错误是

The error i get is

错误166型IChildA不能用作泛型类型或方法的类型参数'T''BaseExtensions.Test&LT; T&GT;(T)。有一个从IChildA'到'IChildB'没有隐式引用转换。

我有一种感觉,那是因为这将是ambigous对于任何实现 IChildB 键,不知道要使用的扩展方法,但该错误信息不会呻吟起来那一边,如果您删除 IBase的firstTry = a.Test(); 行,然后它编译罚款。

I had a feeling it is because it would be ambigous for anything that implements IChildB and wouldn't know which extension method to use, but the error message doesn't moan about that side of it and if you remove the IBase firstTry = a.Test(); line then it compiles fine..

推荐答案

好了,问题是,在重载解析过程中,编译器发现所有适用的候选方法的没有的检查中指定的泛型约束的方法,选取最具体的一个,而则的检查泛型约束。

Okay, the problem is that in the overload resolution process, the compiler finds all applicable candidate methods without checking the generic constraints specified in the method, picks the most specific one, and then checks the generic constraints.

在这种情况下,通用的方法比非通用多一个特定的(如类型参数取代后,它的有效地与一个 IChildA 参数,而不是一个一个方法 IBase的参数) - 但它随后失败的限制

In this case, the generic method is more specific than the non-generic one (as after type parameter substitution, it's effectively a method with an IChildA parameter instead of an IBase parameter) - but it then fails the constraints.

我有一个blog帖子更详细地说明这一点,而另一个using它在一个可怕的方式。

I have a blog post explaining this in more detail, and another one using it in a horrible way.

阅读全文

相关推荐

最新文章