我经常发现自己在做:
foo = foo ?? x;
为什么我不能这样做:
foo ??= x;
编辑:我知道这不是语言的一部分......我的问题是“为什么不”?我发现重复“foo”的必要性令人不愉快并且可能容易出错。它看起来像丑陋一样:
foo = foo + x;
答案 0 :(得分:19)
当我想到它时,
foo = foo ?? x
真的只是
foo = foo != null ? foo : x
并且在那时,+ =的类比开始分崩离析。
答案 1 :(得分:14)
没有理由不能成为这样的运营商,但我怀疑语言的复杂程度虽然微不足道,但却超出了利益(我认为“非常轻微”)。
基本上,语言的任何添加都有很高的清晰度。你说你经常使用它 - 多久一次,真的吗?虽然我认为??
方便,但我不能说我甚至经常使用它。
答案 2 :(得分:14)
通常,C#语言设计团队对添加新语法很保守。他们说,必须权衡语言增加的价值与语言复杂性增加的代价。
Peter Hallam曾担任C#编译器开发主管一段时间,也是C#语言设计团队的成员。他写了关于测量新功能的方法,称为 Yardstick ,尽管他更关注交互式GUI功能而不是语言功能。
本文与??=
:
通常,正确的设计决定是 没有改变什么。这可能是 我学到的最重要的一课 从观看C#中的Anders 语言设计会议。通常是 该语言的领域是在 这有点真实 可以获得的收益。我们可以 防止用户进行常见编码 错误,或者我们可以改进 某种语言的可用性 问题域。然后思考 真的很难,通过所有的 解决问题的选择, 答案就是......没事!甚至 虽然问题是有效的,但它 看起来我们应该能够添加 改善这种情况的东西, 经过仔细的反思,没有 解决问题的方法 不超过解决方案的成本。 许多最重要的和 有价值的决定我见过安德斯 做决定不添加 语言的复杂性,除非 增加值证明了复杂性。 在边缘情况下,他最重要 总之没有任何补充 一些边缘的东西。
答案 3 :(得分:9)
??
在某种意义上不是“操作符”,它使用操作数的值进行“操作”。您应该将其视为语言构造。
假设你有:
node = node.next;
那么您是否希望能够执行以下操作?
node .= next;
我认为??=
不存在的原因与.=
不存在相同。
此外,+=
,*=
等一元运算符在汇编级别具有直接对应运算符。伪汇编:
add reg0, 1
mul reg1, 5
这些运营商的存在只是“自然”。
答案 4 :(得分:5)
没有操作员执行此操作。但是,对于该语言的未来版本,这是一个有趣的建议。我怀疑到目前为止还没有包含它,因为合并运算符??
的主要用例是Nullable类型并且获取值如下所示:
int? testValue;
return testValue ?? 0;
而不是像你的例子那样的赋值操作。此外,虽然+=
保证在所有情况下修改foo的值,但+= 0
,??=
不会。{/ p>
答案 5 :(得分:5)
在讨论??=
与+=
的类比是否合理时,每个人都缺少一个更为简单的答案。
问题:为什么你不能在C#中做foo ??= x;
?
答案:因为every feature starts with minus 100 points,features start out nonexistent and somebody has to make them happen而且很有可能,如果他们添加了该功能,those resources have been spent on something that would have a greater total benefit to the customer base:
......想想所有的时间和精力 必要的设计如何功能 应该工作,钉住所有的边界 条件,然后编码 起来,为它写自动化测试,......写下来 文档和帮助文本,以及 继续维护代码,测试, 和功能的文档 预期的寿命(在此 案件可能是永远的)。可能全部 这些资源已用于 一些会有更大的东西 对客户群的总收益? (答案总是如此 “是的” - 每个人和她的嫂子 可以找到完成句子的方法, “我无法相信他们浪费了所有这些 时间在这个愚蠢的功能而不是 固定...“)
答案 6 :(得分:3)
我没有看到很多理由让你使用??运算符自我赋值变量。
也许你根据恰好是foo
的某个数据库值设置NULL
,所以使用它会更有意义?操作期间的操作符(不需要?? =):
foo = (int?)rows["possiblyNullCount"] ?? 0;
而不是:
foo = (int?)rows["possiblyNullCount"];
foo = foo ?? 0;
答案 7 :(得分:3)
2017年更新:Null-coalescing assignment是C#语言设计团队正在考虑的有效提案。请在https://github.com/dotnet/csharplang/issues/34
投票或加入讨论答案 8 :(得分:2)
主要是因为+ =, - =等几乎被添加,以保持与C& C的兼容性。 C ++。(*)自?? ??不是C或C ++的一部分,不需要添加额外的运算符。
(*)请注意,在C ++中,为类定义运算符时,通常会定义operator + =(),然后基于它实现operator +()。 (这通常是最有效的方式)。 但是,在C#中,一个实现operator +,编译器会根据oper +自动添加operator + =。这就是为什么我说+ =运算符是事后补充的。
答案 9 :(得分:2)
虽然不完全是你要求的(但不是?? =)......你也许可以利用扩展方法。
static void Main(string[] args)
{
object foo = null;
object x = "something";
Console.WriteLine(foo.NullToValue(x));
}
public static class ObjectExtensions
{
public static object NullToValue(this object obj, object value)
{
return obj != null ? obj : value;
}
}
我没有花费大量时间考虑可行的方法,但这似乎无法通过我的示例应用中的气味测试......
答案 10 :(得分:2)
我也很想念 - Ruby毁了我。这是一个类似的构造,您可以在表达式中使用(如果您对副作用过敏):
foo ?? foo = x;
如:
return foo ?? foo = x;
或(仅供说明!):
DoStuff( foo ?? foo = x );
在属性getter之外使用此模式可能不是一个好主意。
答案 11 :(得分:1)
这种陈述风格感觉就像来自财产吸气者的懒惰。在这种情况下,我会选择这种语法
private Foo myFoo;
public Foo MyFoo
{
get
{
return myFoo ?? (myFoo = new Foo());
}
}
答案 12 :(得分:1)
C#8.0中引入了空值分配赋值运算符??=
https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8#null-coalescing-assignment
答案 13 :(得分:-2)
因为C#中没有这样的?? =运算符。
虽然+ =似乎是两个运算符用不同的语法表示,但它只是一个运算符。