2015-10-22 4 views
5

Допустим, я следующий метод определен:Тип вывода несоответствие между методом и методом расширения аргументов

int ReturnNumber(int number) 
{ 
    return number; 
} 

Теперь, давайте скажем, что у меня есть следующие два метода определены; обычный метод:

void Print(Func<int, int> function)

и метод расширения:

static void Print(this Func<int, int> function)

Я могу назвать бывший так:

Print(ReturnNumber); // Regular method call, seems to implicitly convert ReturnNumber to Func<int, int>

, но я не могу сделать что с последним:

ReturnNumber.Print(); // Extension method call, does not seem to do the implicit conversion -- results in compiler error

хотя я могу это сделать:

((Func<int, int>)ReturnNumber).Print(); // I perform the conversion explicitly

Я предполагаю, что есть какое-то «волшебство», что происходит, когда вы передаете метод в качестве аргумента другого метода, и что поэтому компилятор может предположить, что он должен попытаться преобразовать ReturnNumber в Func<int, int>, тогда как компилятор не делает такой вещи для методов расширения. Это верно? Мой вопрос можно суммировать как: почему вы не можете вызвать метод расширения метода, тогда как вы можете вызвать метод расширения на экземпляре делегата? Связано ли это с тем, что компилятор не рассматривает методы как объекты, а только рассматривает делегатов как объекты?

ответ

5

Этот метод группа может быть неявно преобразуется в Func<int, int>, что означает, если вы используете этот метод группы в месте, где Func<int, int> ожидается (например, путем передачи его в метод Кто есть параметр Func<int, int> тогда она способна чтобы преобразовать его в такой делегат.

Но пока вы не превратили эту группу методов в Func<int, int>, вы не можете называть какие-либо методы экземпляра на ней, так как она не имеет. Когда вы явно передали ее Func<int, int> вы меняете это выражение из группы методов (которая сама по себе не является Func<int, int>) в Func<int, int>.