问题
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. It looks just as ugly as:
foo = foo + x;
回答1:
In general, the C# language design team is conservative about adding new syntax. 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. 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.
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. 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, he allmost allways choses nothing over adding something which is marginal.
References:
- The Yardstick
- What Do Programmers Really Do Anyway?
回答2:
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.
回答3:
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.
回答4:
??
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.
回答5:
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:
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.
回答6:
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;
in 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:
... 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...")
回答7:
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 ?? operator during that assignment (which eliminates the need for ??=):
foo = (int?)rows["possiblyNullCount"] ?? 0;
as opposed to:
foo = (int?)rows["possiblyNullCount"];
foo = foo ?? 0;
回答8:
Update 2017: Null-coalescing assignment is an active proposal under consideration by the C# Language Design Team. Please vote or join the discussion at https://github.com/dotnet/csharplang/issues/34
回答9:
Mainly because +=, -= etc were added pretty much as afterthoughts to maintain compatibility with C & C++.(*) Since ?? is not part of C or C++, there was no need to add the extra operator.
(*) Note that in C++, when defining operators for a class, one normally defines operator+=() and then implements operator+() based on it. (It's generally the most efficient way). However, in C#, one implements operator+, and the compiler automatically adds operator+= based on oper+. This is why I say that the += operators are a tacked on afterthought.
回答10:
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...
回答11:
I miss it too - Ruby has ruined me. 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.
回答12:
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());
}
}
回答13:
Because there is no such ??= operator in C#.
Whilst += may seem like two operators represented with different syntax its just one operator.
来源:https://stackoverflow.com/questions/558010/why-cant-i-do-in-c