问题
In this code fragment:
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
is not an Action
for sure since it is returning string
; however x=> Print(x)
is, why?
回答1:
The type of the lambda expression x => Print(x)
is determined based on its context. Since the compiler knows that the lambda is assigned to Action<string>
, the compiler disregards the return type of the Print(s)
method as if it were a statement expression.
This is a valid conversion:
Action<string> myAction = y => Print(y);
In other words, both
Print("something");
and
int x = Print("something");
are correct usages of the Print
method; they can be used in lambdas in the same way.
回答2:
x => Print(x)
is a lambda that is turned into a method here equivalent to:
void MyPrintLambda(string x) { Print(x); }
If the context had called for, say, a Func<string, string>
, it would have been this:
string MyPrintLambda(string x) { return Print(x); }
Or if it was a Func<string, object>
, it would have been this:
object MyPrintLambda(string x) { return Print(x); }
Because the compiler can turn x => Print(x)
into an Action<string>
by simply ignoring the return type (i.e. the first example), it can compile.
回答3:
For the same reason that this would be valid:
foreach (string name in names)
{
Print(name);
}
The Print() method returns a value in that code as well, but no one would expect this to be an error. It's allowed to just throw away the return value.
来源:https://stackoverflow.com/questions/12869426/why-can-lambdas-convert-function-calls-into-actions