为什么我不能做?=在C#中?

时间:2009-02-17 18:01:40

标签: c# language-features

我经常发现自己在做:

foo = foo ?? x;

为什么我不能这样做:

foo ??= x;

编辑:我知道这不是语言的一部分......我的问题是“为什么不”?我发现重复“foo”的必要性令人不愉快并且可能容易出错。它看起来像丑陋一样:

foo = foo + x;

14 个答案:

答案 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 pointsfeatures 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)

答案 13 :(得分:-2)

因为C#中没有这样的?? =运算符。

虽然+ =似乎是两个运算符用不同的语法表示,但它只是一个运算符。