c# - 为什么 `s => x.Append(s)` 可以作为 Action<string> 传递但 `x.Append` 不能?

标签 c# .net lambda

我在尝试传递 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/

相关文章:

c# - 如何模拟作为接口(interface)的接口(interface)属性

c# - 控制台收不到云消息?

c# - 如何在列表中找到子列表的索引?

c# - .csproj 如何知道它的解决方案?

c# - += 运算符与 lambda 运算符的用法

php - 如何获取数组中每个数字的阶乘值?

c# 使用 xml 文件更改按钮和文本框颜色

c# - 将 Json.Net 添加到 Unity3D 项目

c# - 变量声明后的括号

vb.net - 具有多个搜索条件的 Lambda 表达式