简体   繁体   English

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

[英]Why can't I do ??= in C#?

I often find myself doing:我经常发现自己在做:

foo = foo ?? x;

Why can't I do:为什么我不能这样做:

foo ??= x;

Edit : I know it's not part of the language... My question is "why not"?编辑:我知道它不是语言的一部分......我的问题是“为什么不”? I find the necessity to repeat "foo" to be unpleasing and potentially error-prone.我发现重复“foo”的必要性令人不快并且可能容易出错。 It looks just as ugly as:它看起来和下面一样丑陋:

foo = foo + x;

When I think about it,当我想到它时,

foo = foo ?? x 

is really just真的只是

foo = foo != null ? foo : x

and at that point, the analogy to += starts to fall apart.在这一点上,+= 的类比开始分崩离析。

There's no reason why there couldn't be such an operator, but I suspect the added complexity of the language, though slight, outweights the benefit (which I would deem "very slight").没有理由不能有这样的运算符,但我怀疑语言增加的复杂性虽然轻微,但超过了好处(我认为“非常轻微”)。

Basically any addition to the language has a pretty high bar to clear.基本上,对语言的任何添加都有一个相当高的门槛需要清除。 You say you use this quite often - how often, really?你说你经常使用这个 - 真的多久一次? While I deem ??虽然我认为?? handy, I can't say I use even that terribly frequently.方便,我不能说我经常使用它。

In general, the C# language design team is conservative about adding new syntax.一般来说,C# 语言设计团队对添加新语法持保守态度。 They say that the value of an addition to the language must be weighed against the cost of increased complexity in the language.他们说,必须权衡增加语言的价值与增加语言复杂性的成本。

Peter Hallam was the C# Compiler development lead for a while, and also a member of the C# language design team. Peter Hallam 曾担任 C# 编译器开发主管一段时间,同时也是 C# 语言设计团队的成员。 He wrote about his way of measuring a new feature, called the Yardstick , although he was focused more on interactive GUI features than language features.尽管他更关注交互式 GUI 特性而不是语言特性,但他写了他衡量新特性的方法,称为Yardstick

This text is particularly relevant to the question of ??= :这段文字与??=的问题特别相关:

Often the right design decision is to not change anything.通常正确的设计决策是不改变任何东西。 This is probably the most important lesson I've learned from watching Anders in the C# language design meetings.这可能是我在 C# 语言设计会议上观看 Anders 学到的最重要的一课。 Often an area of the language is raised in which there apppears to be some real gains which could be made.通常会提出一个语言领域,其中似乎可以取得一些真正的收获。 We could prevent the user from a common coding error, or we could improve the usabilityof the language for a certain problem domain.我们可以防止用户出现常见的编码错误,或者我们可以提高语言在特定问题领域的可用性。 Then after thinking really hard, through all of the options for addressing the issue, the answer is to do.... nothing, Even though the problem is valid, and it looks like we should be able to add something to improve the situation.然后在认真思考之后,通过解决问题的所有选项,答案是做......什么都不做,即使问题是有效的,看起来我们应该能够添加一些东西来改善这种情况。 after careful reflection there is no way to address the issue which does not cost more than the solution gains.经过仔细思考,没有办法解决这个问题,其成本不超过解决方案的收益。 Many of the most important and valuable decisions I've seen Anders make are decisions to not add complexity to the language unless the added value justifies the complexity, In borderline cases.我见过 Anders 做出的许多最重要和最有价值的决定都是决定不增加语言的复杂性,除非增加的价值证明了复杂性,在临界情况下。 he allmost allways choses nothing over adding something which is marginal.他几乎总是选择添加一些边缘的东西。

References:参考:

?? is not an "operator" in the sense that it does an "operation" with the value of the operands.在它对操作数的值进行“运算”的意义上,它不是“运算符”。 You should view it just as a language construct .您应该将其视为一种语言结构

Suppose you had:假设你有:

node = node.next;

Would you then want to be able to do the following?那么您是否希望能够执行以下操作?

node .= next;

I think ??= doesn't exist for the same reason that .= doesn't exist.我认为??=不存在的原因与.=不存在的原因相同。

Besides, unary operators like += , *= , etc. have direct counterparts at the assembly level.此外,像+=*=等一元运算符在汇编级别有直接对应项。 Pseudo-assembly:伪装配:

add reg0, 1
mul reg1, 5

It's just "natural" that these operators exist.这些运算符的存在是“自然的”。

There is no operator that performs this operation.没有执行此操作的操作员。 However, it's an interesting suggestion for a future version of the language.但是,对于该语言的未来版本,这是一个有趣的建议。 I suspect that it hasn't been included thus far because the primary use-case for the coalescing operator, ??我怀疑到目前为止还没有包含它,因为合并运算符的主要用例是?? , is with the Nullable type and getting the value as in: , 具有 Nullable 类型并获取值,如下所示:

int? testValue;

return testValue ?? 0;

Rather than in assignment operations like your example.而不是像您的示例那样进行分配操作。 Also, whereas += is guaranteed to modify the value of foo in all cases but += 0 , ??= would not.此外,虽然+=保证在所有情况下修改 foo 的值,但+= 0??=不会。

There's a much simpler answer everyone is missing while discussing whether the analogy of ??= to += makes sense.在讨论??=+=的类比是否有意义时,每个人都缺少一个更简单的答案。

Question: Why can't you do foo??= x;问题:为什么你不能做foo??= x; in C#?在 C# 中?

Answer: Because every feature starts with minus 100 points , features start out nonexistent and somebody has to make them happen and most likely if they added that feature, those resources have been spent on something that would have a greater total benefit to the customer base :回答:因为每个功能都从负 100 分开始,功能开始时不存在,必须有人让它们发生,而且很可能如果他们添加了该功能, 那么这些资源就会花在对客户群有更大总利益的事情上

... think of all the time and effort necessary to design how the feature should work, nail all the boundary conditions, then code it up, write automated tests for it, ... write up the documentation and help text, and continue maintaining the code, tests, and documentation for the feature's anticipated lifetime (which in this case is probably forever). ...考虑设计该功能的工作方式所需的所有时间和精力,确定所有边界条件,然后对其进行编码,为其编写自动化测试,...编写文档和帮助文本,并继续维护该功能的预期生命周期(在这种情况下可能是永远的)的代码、测试和文档。 Could all those resources have been spent on something that would have a greater total benefit to the customer base?是否可以将所有这些资源都花在对客户群有更大总体利益的事情上? (The answer to that is always "Yes"—everybody and her sister-in-law can find a way to finish the sentence, "I can't believe they wasted all that time on this stupid feature instead of fixing...") (答案总是“是”——每个人和她的嫂子都能想办法完成这句话,“我不敢相信他们把所有时间都浪费在这个愚蠢的功能上而不是修复……” )

Update 2017 : Null-coalescing assignment is an active proposal under consideration by the C# Language Design Team. 2017 年更新:空合并赋值是 C# 语言设计团队正在考虑的一项积极提案。 Please vote or join the discussion at https://github.com/dotnet/csharplang/issues/34请在https://github.com/dotnet/csharplang/issues/34投票或加入讨论

I don't see many reasons why you would use the??我不明白为什么你会使用 ?? operator to self-assign a variable.运算符自行分配变量。

Perhaps you're setting foo based on some database value that happens to be NULL , so it would make more sense to use the??也许您正在根据恰好为NULL的某些数据库值设置foo ,因此使用 ?? 更有意义operator during that assignment (which eliminates the need for??=):该赋值期间的运算符(这消除了对 ??= 的需要):

foo = (int?)rows["possiblyNullCount"] ?? 0;

as opposed to:而不是:

foo = (int?)rows["possiblyNullCount"];
foo = foo ?? 0;

Mainly because +=, -= etc were added pretty much as afterthoughts to maintain compatibility with C & C++.(*) Since??主要是因为 +=、-= 等几乎是事后添加的,以保持与 C 和 C++ 的兼容性。(*) 因为?? is not part of C or C++, there was no need to add the extra operator.不是 C 或 C++ 的一部分,因此无需添加额外的运算符。

(*) Note that in C++, when defining operators for a class, one normally defines operator+=() and then implements operator+() based on it. (*) 请注意,在C++中,为类定义运算符时,通常定义operator+=(),然后基于它实现operator+()。 (It's generally the most efficient way). (这通常是最有效的方式)。 However, in C#, one implements operator+, and the compiler automatically adds operator+= based on oper+.但是在C#中,实现了operator+,编译器会在oper+的基础上自动添加operator+=。 This is why I say that the += operators are a tacked on afterthought.这就是为什么我说 += 运算符是事后才想到的。

While not exactly what you are asking for (it's not??=)... You could perhaps leverage Extension Methods.虽然不完全是您要求的(不是??=)...您也许可以利用扩展方法。

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;
    }
}

I haven't spent an exhaustive amount of time thinking of possible ways this won't work, but it does seem to pass the smell test in my sample application...我没有花大量时间思考这可能行不通的可能方式,但它似乎确实通过了我的示例应用程序中的气味测试......

I miss it too - Ruby has ruined me.我也想念它——Ruby 毁了我。 Here is a similar construct that you can use in an expression (if you aren't allergic to side-effects):这是一个类似的结构,您可以在表达式中使用(如果您对副作用不过敏的话):

foo ?? foo = x;

as in:如:

return foo ?? foo = x;

or (for illustration only:):或(仅供说明:):

DoStuff( foo ?? foo = x );

Using this pattern outside of a property getter is probably not a great idea.在属性获取器之外使用此模式可能不是一个好主意。

The null-coalescing assignment operator ??= was introduced in C# 8.0空合并赋值运算符??=是在 C# 8.0 中引入的

https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8#null-coalescing-assignment https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8#null-coalescing-assignment

That style of statement feels like a lazy-load from a property getter.这种语句风格感觉像是来自属性获取器的延迟加载。 In which case, I would choose this syntax在这种情况下,我会选择这种语法

private Foo myFoo;
public Foo MyFoo
{
    get
    {
        return myFoo ?? (myFoo = new Foo());
    }
}

Because there is no such??= operator in C#.因为C#中没有这种??=运算符。

Whilst += may seem like two operators represented with different syntax its just one operator.虽然 += 看起来像是两个用不同语法表示的运算符,但它只是一个运算符。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM