Может быть, это прояснит:
public class SomeClass
{
static void foo(int x) { }
static void foo(string s) { }
static void bar<T>(Action<T> f){}
static void barz(Action<int> f) { }
static void test()
{
Action<int> f = foo;
bar(f);
barz(foo);
bar(foo);
//these help the compiler to know which types to use
bar<int>(foo);
bar( (int i) => foo(i));
}
}
foo не является действием - foo является группой методов.
- В операторе присваивания компилятор может четко указать, о каком foo вы говорите, поскольку указан тип int.
- В операторе barz (foo) компилятор может определить, о каком foo вы говорите, поскольку указан тип int.
- В выражении bar (foo) это может быть любой foo с одним параметром - поэтому компилятор сдается.
Редактировать: я добавил два (более) способа, чтобы помочь компилятору выяснить тип (то есть - как пропустить шаги вывода).
Из моего прочтения статьи в ответе JSkeet, решение не выводить тип, похоже, основано на сценарии взаимного вывода, таком как
static void foo<T>(T x) { }
static void bar<T>(Action<T> f) { }
static void test()
{
bar(foo); //wut's T?
}
Поскольку общая проблема была неразрешимой, они решили оставить конкретные проблемы, где решение существует как нерешенные.
Как следствие этого решения, вы не будете добавлять перегрузку для метода и получать большую путаницу типов от всех вызывающих, которые используются в одной группе методов-членов. Я думаю, это хорошо.