我在尝试传递 StringBuilder
时注意到一些奇怪的事情的 Append
使用 Action<string>
的函数的方法.
public void DoStuff(Action<string> handler)
{
// Do stuff, call handler("data");
}
出于测试目的,我只想将数据写入 StringBuilder
,所以我试着这样调用它:
var output = new StringBuilder();
DoStuff(output.Append);
但是,这会产生编译错误,因为 Append
方法与所需的签名不匹配(它返回对 StringBuilder
的引用,而不是我的方法想要的无效):
'System.Text.StringBuilder System.Text.StringBuilder.Append(string)' has the wrong return type
想都没想,把代码改成了这样:
var output = new StringBuilder();
DoStuff(s => output.Append(s));
这编译得很好。
然后我就糊涂了;意识到s => output.Append(s)
还应该返回 StringBuilder
,它们不一样吗?
那么,为什么会这样呢?为什么可以s => output.Append(s)
静默丢弃返回值,但 output.Append
不能吗?
最佳答案
s => output.Append(s)
创建一个新的 lambda 表达式,(根据上下文)推断其返回类型为 void
。
因此,表达式主体的值将被忽略。
这被编译为一个单独的方法,该方法调用 Append()
并返回 void(这与委托(delegate)完全匹配)
相反,当您尝试将方法组转换为委托(delegate)时,转换必须完全匹配。
规范 (§6.5) 说:
Specifically, an anonymous function F is compatible with a delegate type D provided:
- If the body of F is an expression, and either D has a void return type or F is async and D has the return type Task, then when each parameter of F is given the type of the corresponding parameter in D, the body of F is a valid expression (wrt §7) that would be permitted as a statement-expression (§8.6).
关于c# - 为什么 `s => x.Append(s)` 可以作为 Action<string> 传递但 `x.Append` 不能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24191090/