简体   繁体   English

泛型扩展方法

[英]Extension methods with generics

I was looking at this question and i was curious why this deosn't compile. 我一直在看这个问题,我很好奇为什么不编译。

Given this code, can anyone explain why the call to IBase.Test() doesn't resolve to the correct extension method? 有了这段代码,谁能解释为什么对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();
    }
}

The error i get is 我得到的错误是

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'.

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(); 我有一种感觉,因为它对于实现IChildB任何事物都是IChildB ,并且不知道要使用哪种扩展方法,但是错误消息不会IBase firstTry = a.Test();它的这一面,并且如果您删除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. 好的,问题是,在重载解析过程中,编译器会找到所有适用的候选方法, 而不会检查方法中指定的通用约束,选择最具体的约束, 然后检查通用约束。

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. 在这种情况下,泛型方法比非泛型方法更具体(就像在类型参数替换之后一样,它实际上是带有IChildA参数而不是IBase参数的方法)-但是,它使约束失效。

I have a blog post explaining this in more detail, and another one using it in a horrible way . 我有一篇博客文章更详细地解释了这一点,另一篇文章以一种可怕的方式使用它

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM