试图通过一个时,我发现了一些奇怪StringBuilder的Append方法来夺走了一个功能Action<string>.
public void DoStuff(Action<string> handler)
{
// Do stuff, call handler("data");
}
Run Code Online (Sandbox Code Playgroud)
出于测试目的,我只想将数据写入a StringBuilder,所以我试着像这样调用它:
var output = new StringBuilder();
DoStuff(output.Append);
Run Code Online (Sandbox Code Playgroud)
但是,这会产生编译错误,因为该Append方法与所需的签名不匹配(它返回一个引用StringBuilder,而不是我的方法所需的void):
'System.Text.StringBuilder System.Text.StringBuilder.Append(string)'返回类型错误
不假思索,我把代码更改为:
var output = new StringBuilder();
DoStuff(s => output.Append(s));
Run Code Online (Sandbox Code Playgroud)
这编译好了.
然后我感到困惑; 意识到s => output.Append(s)还应该回归StringBuilder,不是他们一样吗?
那么,为什么这有效呢?为什么可以s => output.Append(s)静默丢弃返回值,但output.Append不能?
SLa*_*aks 20
s => output.Append(s)创建一个新的lambda表达式,该表达式(从上下文中)推断出返回类型为void.
因此,忽略表达式主体的值.
这被编译为一个单独的方法,调用Append()并返回void(这与委托完全匹配)
相反,当您尝试将方法组转换为委托时,转换必须完全匹配.
规范(§6.5)说:
具体来说,匿名函数F与提供的委托类型D兼容:
- 如果F的主体是一个表达式,并且D具有void返回类型或者F是异步而D具有返回类型Task,那么当F的每个参数都给出D中相应参数的类型时,F的主体是一个有效的表达式(wrt§7),它将被允许作为statement-expression(§8.6).
| 归档时间: |
|
| 查看次数: |
422 次 |
| 最近记录: |