簡體   English   中英

泛型擴展方法

[英]Extension methods with 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<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任何事物都是IChildB ,並且不知道要使用哪種擴展方法,但是錯誤消息不會IBase firstTry = a.Test();它的這一面,並且如果您刪除IBase firstTry = a.Test(); 行,然后編譯就可以了。

好的,問題是,在重載解析過程中,編譯器會找到所有適用的候選方法, 而不會檢查方法中指定的通用約束,選擇最具體的約束, 然后檢查通用約束。

在這種情況下,泛型方法比非泛型方法更具體(就像在類型參數替換之后一樣,它實際上是帶有IChildA參數而不是IBase參數的方法)-但是,它使約束失效。

我有一篇博客文章更詳細地解釋了這一點,另一篇文章以一種可怕的方式使用它

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM