Почему lambdas может преобразовывать вызовы функций в Action?
В этом фрагменте кода:
List<String> names = new List<String>();
names.Add("Bruce");
names.Add("Tom");
names.Add("Tim");
names.Add("Richard");
names.ForEach(x => Print(x));
private static string Print(string s)
{
Console.WriteLine(s);
return s;
}
Print
не является Action
, так как он возвращает string
; однако x=> Print(x)
есть, почему?
Ответы
Ответ 1
Тип выражения лямбда x => Print(x)
определяется на основе его контекста. Поскольку компилятор знает, что лямбда назначена Action<string>
, компилятор игнорирует возвращаемый тип метода Print(s)
, как если бы это было выражение выражения.
Это допустимое преобразование:
Action<string> myAction = y => Print(y);
Другими словами, оба
Print("something");
и
int x = Print("something");
являются правильными применениями метода Print
; они могут быть использованы в лямбдах таким же образом.
Ответ 2
x => Print(x)
- это лямбда, которая превращается в метод, эквивалентный:
void MyPrintLambda(string x) { Print(x); }
Если бы контекст вызывал, скажем, a Func<string, string>
, это было бы так:
string MyPrintLambda(string x) { return Print(x); }
Или, если это был Func<string, object>
, это было бы так:
object MyPrintLambda(string x) { return Print(x); }
Поскольку компилятор может превратить x => Print(x)
в Action<string>
, просто игнорируя возвращаемый тип (т.е. первый пример), он может скомпилировать.
Ответ 3
По той же причине, что это было бы верно:
foreach (string name in names)
{
Print(name);
}
Метод Print() возвращает значение в этом коде, но никто не ожидал, что это будет ошибка. Это позволило просто выбросить возвращаемое значение.