C# 为什么我必须在lambda表达式中使用out/ref显式定义所有类型?
如果我有一个用C# 为什么我必须在lambda表达式中使用out/ref显式定义所有类型?,c#,lambda,C#,Lambda,如果我有一个用out关键字定义的委托,如下所示: delegate int D<TResult, TArgument>(TArgument argument, out TResult result); D<int, int> d = (int arg, out int rst) =>{...} //correct 更新 看来这个问题还在C#design小组讨论中。官方的C#语言设计报告中围绕这一公开问题提出了一系列建议。似乎C#语言的设计者决定严
out
关键字定义的委托,如下所示:
delegate int D<TResult, TArgument>(TArgument argument, out TResult result);
D<int, int> d = (int arg, out int rst) =>{...} //correct
更新
看来这个问题还在C#design小组讨论中。官方的C#语言设计报告中围绕这一公开问题提出了一系列建议。似乎C#语言的设计者决定严格来说可以有两种类型的匿名函数签名-它们被定义为显式匿名函数签名和隐式匿名函数签名 显式匿名函数签名是一个相当标准的参数列表-在
()
括号之间,用逗号分隔,每个参数定义都包含一个可选的修饰符(out
或ref
),一个类型和一个标识符
隐式匿名函数签名是一个非常简单的参数列表-在()
括号之间,用逗号分隔,每个参数定义只包含一个标识符
你不能在这两种形式之间混搭,你必须选择其中一种。这可能会使解析更简单,并使类型推断成为一个开/关概念,而不是一个“半开”(这就是CS0748
真正要说的)
通过能够使用一种或另一种类型的签名谈论lambda,这当然可以让他们更容易地指定语言中的其他规则
因此,如果您需要包含一个修饰符(out
),那么您就没有选择了—您必须使用显式匿名函数签名
来自C#规范第5版: lambda表达式:
- 匿名函数签名
匿名函数体=>
显式匿名函数signatureopt块委托
- 显式匿名函数签名
- 隐式匿名函数签名
显式匿名函数参数listopt(
)
- 显式匿名函数参数
- 显式匿名函数参数列表
显式匿名函数参数,
- 匿名函数参数modifieropt类型标识符
ref
out
隐式匿名函数参数listopt(
)
- 隐式匿名函数参数
- 隐式匿名函数参数
- 隐式匿名函数参数列表
隐式匿名函数参数,
- 标识符
因为您必须为委托定义提供一个正式参数,而您正试图传递实际参数。@er sho抱歉,我不明白您的意思。你能说得更具体些吗?“很明显,
rst
和arg
必须是int
”-为什么这么说?答案是因为CLR团队在设计语言功能时必须权衡,在这种情况下,编译器需要知道此时的类型,此外,他们选择像这样实现它this@Damien_The_Unbeliever因为D
委托定义为D
,所以它提供了此信息。如果没有out
关键字,您将看到`D=(arg,rst)=>{…}`compile。它不可能是任何其他类型的,因为它被定义为'D',问题是他们是这样做的,但没有令人信服的理由,我认为它可以改进。这肯定是编译器的问题,而不是CLR限制。请看我的更新,它仍在讨论中。@joe-嗯,就我个人而言,我很高兴我们不能得到“意外ref
”。任何方法都可能改变它的参数,不管我们认为这是好事还是坏事。没有标记有ref
的Lambda做这样的事情并且在其他地方有副作用可能会令人不快。
D<int, int> d1 = ( arg, out rst) => {...} //CS2046
D<int, int> d2 = (arg, out int rst) => {...} //CS0748
D<int, int> d1 = ( arg, out rst) => {...} ////won't compile