Функция функции работает в одном направлении, а не в другом - PullRequest
6 голосов
/ 18 марта 2012

Я пытаюсь написать функцию, которая принимает функцию в качестве одного из аргументов - задачу, которую я делал много раз раньше.Это отлично работает:

int RunFunction(Func<int,int> f, int input) {
    return f(input);
}
int Double(int x) {
    return x*2;
}

// somewhere else in code
RunFunction(Double,5);

Но это не работает:

public static class FunctionyStuff {
    public static int RunFunction(this Func<int,int> f, int input) {
        return f(input);
    }
}

// somewhere else in code
Double.RunFunction(5);

Есть идеи, почему первый работает, а второй нет?

Ответы [ 2 ]

5 голосов
/ 18 марта 2012

Первая версия выполняет преобразование группы методов как часть соответствия "аргумент параметру".Это преобразование не происходит для методов расширения.То же самое верно для лямбда-выражений - вы также не можете написать:

((int x) = > x * 2).RunFunction(10);

.

В разделе 7.6.5.2 спецификации C # 4 приводятся подробности вызовов метода расширения.Он начинается с требования, чтобы вызов метода имел одну из следующих форм:

expr.identifier ( )
expr.identifier ( args )
expr.identifier < typeargs > ( )
expr.identifier < typeargs > ( args )

тип выражения (expr) затем используется в этом правиле:

Метод расширения C i .M j соответствует приемлемо , если

  • [...]
  • Неявное преобразование идентификатора, ссылки или бокса существует из expr в тип первого параметра M j .

Аннотированная версия спецификации затем включает этот комментарий Эрика Липперта:

Это правило гарантирует, что создание метода, расширяющего double, также не расширяет int.Это также гарантирует, что методы расширения не определены для анонимных функций или групп методов.

0 голосов
/ 18 марта 2012

Методы расширения"вызываются так, как если бы они были методами экземпляра для расширенного типа".

В вашем случае Double не является экземпляром, поэтому вы не можете вызвать метод расширения для него.

...