Почему добавление типа возврата мешает мне использовать синтаксис группы методов? - PullRequest
3 голосов
/ 22 октября 2010

Я пытаюсь использовать группу методов в лямбда-выражении, например:

public class Foo { public void Hello(string s) { } }

void Test()
{
    // this works as long as Hello has a void return type
    Func<Foo, Action<string>> a = foo => foo.Hello;
}

Когда я изменяю тип возврата Hello на int, я получаю

'Bar.Hello (string)' имеет неправильный тип возврата.

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

Есть идеи?

(Моя цель, fwiw, заключается в том, чтобы иметь возможность ссылаться на многочисленные методы, которые имеют разные типы возвращаемых значений и множество строковых аргументов. Я даже не собираюсь вызывать их - я просто хочу обдумать их атрибуты. как безопасность лямбд, однако, вместо простого ввода строк имени метода.)


Редактировать : чтобы уточнить мои причины желания использовать Action<string>: int в моем примере может быть любого из нескольких типов. Я пытался шаблонизировать этот тип -

void Set<T>(Func<Foo, Func<string, T>> a) { }
void Test() { Set(foo => foo.Hello); }  // fails

- но компилятор не может получить T (предположительно по тем же причинам, по которым я не могу перегрузить тип возвращаемого значения?).

Есть еще идеи? В этом случае я не против какого-то безумного размышления, пока я могу заставить компилятор проверить имя этой группы методов.

Ответы [ 2 ]

7 голосов
/ 22 октября 2010

Когда он имеет тип возврата не void, он больше не совместим с Action<string>.Другими словами, это тоже не получится:

int Foo(string s) { return 10; }

// Error: wrong return type
Action<string> action = new Action<string>(Foo);

По причинам почему это не разрешено, см. Сообщение Эрика Липперта в блоге на "Пустота инвариантна" .

Вы должны использовать синтаксис группы методов следующим образом:

public class Foo { public int Hello(string s) { return 10; } }

void Test()
{
    Func<Foo, Func<string, int>> a = foo => foo.Hello;
}

Это работает для меня как в VS2008, так и в VS2010.В C # 4 произошли некоторые изменения в преобразованиях групп методов и выводе типов - детали меня, к сожалению, избегают - но я не верю, что эти изменения затронули этот случай.

6 голосов
/ 22 октября 2010

С возвращаемым пустым типом, foo.Hello - Action<string>.С возвращаемым типом int теперь это Func<string, int>.

Для обработки нескольких типов возвращаемых значений - и при условии, что вам не нужно ничего делать с возвращаемым значением - вы можете тривиально обернуть не пустые функции следующим образом:

Func<Foo, Action<string>> a = foo => s => foo.Hello(s);
...