C# 为什么can`s=>;x、 Append(s)`可以作为操作传递<;字符串>;但是'x.Append'可以';T
当我试图将C# 为什么can`s=>;x、 Append(s)`可以作为操作传递<;字符串>;但是'x.Append'可以';T,c#,.net,lambda,C#,.net,Lambda,当我试图将StringBuilder的Append方法传递给执行操作的函数时,我注意到了一些奇怪的情况 但是,这会产生编译错误,因为Append方法与所需的签名不匹配(它返回对StringBuilder的引用,而不是像我的方法所希望的那样无效): “System.Text.StringBuilder System.Text.StringBuilder.Append(string)”的返回类型错误 不假思索,我将代码更改为: var output = new StringBuilder(); Do
StringBuilder
的Append
方法传递给执行操作的函数时,我注意到了一些奇怪的情况
但是,这会产生编译错误,因为Append
方法与所需的签名不匹配(它返回对StringBuilder
的引用,而不是像我的方法所希望的那样无效):
“System.Text.StringBuilder System.Text.StringBuilder.Append(string)”的返回类型错误
不假思索,我将代码更改为:
var output = new StringBuilder();
DoStuff(s => output.Append(s));
这很好
然后我感到困惑;意识到s=>output.Append
也应该返回StringBuilder
,它们不一样吗
那么,为什么会这样呢?为什么s=>output.Append(s)
可以默默地丢弃返回值,而output.Append(s)
却不能?s=>output.Append(s)
创建一个新的lambda表达式,该表达式(从上下文)被推断为返回类型为void
因此,表达式体的值被忽略。
这被编译成一个单独的方法,该方法调用Append()
,并返回void(与委托完全匹配)
相反,当您尝试将方法组转换为委托时,转换必须完全匹配
规范(§6.5)规定:
具体而言,匿名函数F与提供的委托类型D兼容:
- 如果F的主体是一个表达式,并且D具有无效的返回类型,或者F是异步的,并且D具有返回类型任务,那么当F的每个参数都给定了D中相应参数的类型时,F的主体是一个有效的表达式(wrt§7),它将被允许作为语句表达式(§8.6)
我很困惑,如何不使用多行lambda将其转换为:s=>{return output.Append(s);}
。我认为他们是平等的。@gunr2171:不;它被推断为不返回任何内容/@gunr2171 C#中的Lambda表达式总是根据其用法进行推断s=>output.Append本身没有意义。它只有在编译器可以推断类型的地方才有意义。这是因为lambda表达式也可以与表达式树一起使用,例如expression expr=s=>output.Append
。这就推断lambda是一种甚至不是委托的类型代码>是一个编译错误。编译器无法推断表达式类型,因此使用var
是不正确的。@DannyTuppeny:请参阅我的编辑以获取相关的规范引用。请注意
var output = new StringBuilder();
DoStuff(output.Append);
var output = new StringBuilder();
DoStuff(s => output.Append(s));