C# 为什么lambda可以将函数调用转换为操作?

C# 为什么lambda可以将函数调用转换为操作?,c#,.net,c#-4.0,C#,.net,C# 4.0,在此代码片段中: 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); retur

在此代码片段中:

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;
}
列表名称=新列表();
名称。添加(“Bruce”);
姓名。加上(“汤姆”);
名称。添加(“Tim”);
姓名。添加(“Richard”);
name.ForEach(x=>Print(x));
私有静态字符串打印(字符串s)
{
控制台。写入线(s);
返回s;
}

打印
肯定不是一个
操作
,因为它返回的是
字符串
;然而,
x=>Print(x)
是,为什么?

lambda表达式的类型
x=>Print(x)
是根据上下文确定的。由于编译器知道lambda被分配给
操作
,因此编译器会忽略
打印
方法的返回类型,就像它是一个语句表达式一样

这是一个有效的转换:

Action<string> myAction = y => Print(y);

打印方法的正确用法;它们可以以相同的方式在lambda中使用。

x=>Print(x)
是一种lambda,在这里转化为一种方法,相当于:

void MyPrintLambda(string x) { Print(x); }
如果上下文要求,比如说,一个
Func
,它应该是这样的:

string MyPrintLambda(string x) { return Print(x); }
object MyPrintLambda(string x) { return Print(x); }
或者,如果它是一个
Func
,它应该是这样的:

string MyPrintLambda(string x) { return Print(x); }
object MyPrintLambda(string x) { return Print(x); }

由于编译器可以通过忽略返回类型(即第一个示例)将
x=>Print(x)
转换为
操作
,因此它可以编译。

,原因与此相同:

foreach (string name in names)
{
    Print(name);
}

Print()方法也会在代码中返回一个值,但没有人会认为这是一个错误。只允许丢弃返回值。

既然打印返回字符串,为什么编译器可以将返回类型作为void和match操作?因为处理字符串的合法方法是丢弃它。你不需要特别声明你正在丢弃一个返回值——不使用它就足够了。事实上,几乎每次你赋值时,你都在做同样的事情,因为赋值表达式返回赋值!因此,分配raible的操作也在做同样的事情。最后一位不太正确,
名称。ForEach(Print)
不会编译,因为
Print
不能转换为
action
x=>Print(x)
是,但是,因为表达式的类型是根据用法定义的。请改进这个问题的标题。谷歌用它来为搜索结果命名,而你的标题根本不可谷歌搜索。