Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/276.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么我必须在lambda表达式中使用out/ref显式定义所有类型?_C#_Lambda - Fatal编程技术网

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