微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么不能在 C# 中加入空合并赋值运算符? 空合并运算符空合并赋值运算符问题免责声明

如何解决为什么不能在 C# 中加入空合并赋值运算符? 空合并运算符空合并赋值运算符问题免责声明

空合并运算符

我最喜欢的 C# 特性之一是空合并运算符,我已经使用了很长时间:

// Simple fallback
var foo = specifiedValue ?? fallbackValue;

// Fetch if not present
foo = foo ?? getAFoo();

// Parameter validation
foo = foo ?? throw new ArgumentNullException(nameof(foo));

// Combination of the two prevIoUs examples
foo = foo ?? getAFoo() ?? throw new Exception("Couldn't track down a foo :( ");

空合并赋值运算符

我也喜欢新的 C# 8 运算符,它缩短了“如果不存在则获取”用例:

foo = foo ?? getAFoo(); // null-coalescing
foo ??= getAFoo(); // null-coalescing assignment

问题

我曾希望也许我也可以在参数验证用例中使用空合并赋值运算符,但似乎不允许这样做。这就是我想做的:

foo = foo ?? throw new ArgumentNullException(nameof(foo)); // Does compile
foo ??= throw new ArgumentNullException(nameof(foo));  // Does not compile

谁能解释为什么空合并赋值运算符适用于“如果不存在则获取”场景而不适用于参数验证场景?

https://dotnetfiddle.net/W8cNPo

免责声明

我意识到 ... ??= throw ... 可能不是最易读的方法。我的问题与样式/可读性无关,因为它只是想了解这个运算符的一个怪癖。

谢谢!

解决方法

?? 的答案相当简单。它只是按照 documentation 中所述的方式实现:

空合并运算符 ??如果它不为空,则返回其左侧操作数的值;否则,它评估右侧操作数并返回其结果。这 ??如果左侧操作数的计算结果为非空,则运算符不会计算其右侧操作数。

??= throw 的答案有点棘手。似乎这会很有用(或者从开发人员的角度来看可能是一致的),但这是有原因的。如果您深入研究 ??= 运算符的 C# 8.0 Null Coalescing Assignment proposal,您会发现这一行(我强调了):

否则,a ??= b 的类型是 A。a ??= b 在运行时被评估为 a ?? (a = b),除了 a 只计算一次。

这意味着您的作业将评估为

foo ?? (foo = throw new ArgumentNullException(nameof(foo)))

这在语法上无效。

他们是否必须以这种方式实施?不,他们可以以不同的方式实施它,但他们没有。提案接着说这个

与任何语言功能一样,我们必须质疑语言的额外复杂性是否会通过为将从该功能中受益的 C# 程序主体提供的额外清晰度来弥补。

看起来,额外的复杂性不被认为是有必要的,因为替代方案非常好。

借用 Julien 对该问题的评论(谢谢!),meeting notes 提供了更多背景信息

在右侧抛出表达式

是否应该允许以下情况:a ??= throw new Exception?现在只允许在某些地方使用 throw 表达式,因此我们必须明确添加支持。如果特征等价于 a = a ?? b 其中 b 是投掷,而不是 a ?? (a = b).

结论

不支持

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。