Методы расширения с обобщениями - PullRequest
2 голосов
/ 23 марта 2011

Я смотрел на этот вопрос, и мне было любопытно, почему этот deos не компилируется.

Учитывая этот код, кто-нибудь может объяснить, почему вызов 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 Ответ

5 голосов
/ 23 марта 2011

Хорошо, проблема в том, что в процессе разрешения перегрузки компилятор находит все подходящие методы-кандидаты без , проверяя общие ограничения, указанные в методе, выбирает наиболее конкретный и затем проверяет общие ограничения.

В этом случае универсальный метод более специфичен, чем неуниверсальный (так как после подстановки параметра типа это фактически метод с параметром IChildA вместо IBase параметр), но затем он не соответствует ограничениям.

У меня есть сообщение в блоге , объясняющее это более подробно, и еще одно , использующее его ужасным образом .

...