c# - 为什么我必须在 lambda 表达式中使用 out/ref 显式定义所有类型?
问题描述
如果我有一个用out
这样的关键字定义的委托:
delegate int D<TResult, TArgument>(TArgument argument, out TResult result);
我想用一个 lambda 表达式来设置它,它必须是这样的:
D<int, int> d = (int arg, out int rst) =>{...} //correct
以下两种说法是错误的:
D<int, int> d1 = ( arg, out rst) => {...} //CS2046
D<int, int> d2 = (arg, out int rst) => {...} //CS0748
所以我的问题是:为什么 C# 会这样设计?我了解您必须声明out
才能清楚并能够超载。但很明显,rst
而且arg
必须如此int
。为什么我必须定义所有这些?CS0748告诉我不要这样做,但不知道为什么。
在我看来,这是应该的。是否有任何异常可能导致问题?
D<int, int> d1 = ( arg, out rst) => {...} ////won't compile
更新
看起来这个问题仍在 C# 设计组中讨论。在官方 C# 语言设计 repo #338中有很多关于这个未解决问题的建议。
解决方案
似乎 C# 语言的设计者决定严格来说可以有两种匿名函数签名——它们被定义为显式匿名函数签名和隐式匿名函数签名。
显式匿名函数签名是一个相当标准的参数列表——在括号之间()
并用逗号分隔,每个参数定义由一个可选的修饰符(out
或ref
)、一个类型和一个标识符组成。
隐式匿名函数签名是一个非常简单的参数列表 - 在括号之间()
并用逗号分隔,每个参数定义仅包含一个标识符。
你不能在两种形式之间混搭,你必须选择其中一种。这可能使解析更简单,并使类型推断成为一个关闭/开启的概念,而不是“半开”的概念(这就是CS0748
真正的意思)。
它当然可以让他们通过使用一种或另一种类型的签名来讨论 lambda,从而使语言中的其他规则更容易指定。
因此,如果您需要包含修饰符 ( out
),您将别无选择 - 您必须使用显式匿名功能签名。
来自 C# 规范,版本 5:
lambda 表达式:
- 匿名函数签名
=>
匿名函数体匿名方法表达式:
delegate
显式匿名功能签名选择 块匿名函数签名:
显式匿名函数签名
隐式匿名函数签名
显式匿名函数签名:
(
显式匿名函数参数列表选项)
显式匿名函数参数列表:
显式匿名函数参数
显式匿名函数参数列表
,
显式匿名函数参数显式匿名函数参数:
- 匿名函数参数修饰符opt 类型 标识符
匿名函数参数修饰符:
ref
out
隐式匿名函数签名:
(
隐式匿名函数参数列表选项)
隐式匿名函数参数
隐式匿名函数参数列表:
隐式匿名函数参数
隐式匿名函数参数列表
,
隐式匿名函数参数隐式匿名函数参数:
- 标识符
推荐阅读
- sitecore - 在哪种情况下我们可以使用视图或控制器渲染?
- sql - SQL Server 中的情况
- powershell - 如何使用 Invoke-Sqlcmd (powershell) 在 Azure Sql 数据库中创建用户?
- c# - 从其他进程 C# 获取输入和输出
- javascript - 如何使用生成器函数作为事件侦听器内部的回调
- xcode - 找不到“Frameworks/App.framework/flutter_assets”的资产路径
- python - tkinter - 单选按钮可以控制多个变量吗?
- java - 如何为我的手机中安装的 whatsapp、facebook 或其他应用程序创建共享按钮
- java - 如何有效地比较两个产品列表
- linux - rm 命令未通过 cron 执行