15

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;
JoelFan
  • 37,465
  • 35
  • 132
  • 205
  • 2
    Unless one of the designers of the C# language comes to Stack Overflow, you can't get an authoritative answer to "why?". Try asking a different question, like "what are some alternatives to `??=`?" or "how to I give feedback to the C# team?" – Jay Bazuzi Feb 17 '09 at 18:50

14 Answers14

19

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.

Brian Genisio
  • 47,787
  • 16
  • 124
  • 167
  • This was my thought too. I'd be interested in the IL for both statements, I think they're the same. And then ??= doesn't hold up. – Anthony Mastrean Feb 17 '09 at 18:08
  • You might be interested in this: http://stackoverflow.com/questions/547249/-operator-vs-if-statement-performance/547333#547333 Apparently the IL is not actually quite the same. – mqp Feb 17 '09 at 18:16
14

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.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
14

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:

Jay Bazuzi
  • 45,157
  • 15
  • 111
  • 168
9

?? 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.

Ates Goral
  • 137,716
  • 26
  • 137
  • 190
  • I think you meant "node .= next;" instead of "node .= node;" – Biswanath Feb 17 '09 at 18:49
  • 2
    What's sacred about the difference between an operator and a language construct? "node .= next;" has at least syntactic parallels, and consistent syntax is always nice. Nor do I particularly care what operators have direct assembler counterparts. – David Thornley Feb 17 '09 at 19:15
  • I don't find the assembly analogy meaningful. add reg0,1 is not the same as x+=1. load reg0,st+34;add reg0,1;store st+34,reg0 is closer to += in meaning. – jmucchiello Feb 17 '09 at 19:18
  • @David Thornley: It's about polluting the language vocabulary. IMHO, the more there are multiple, unnecessary ways of writing the same thing, the more unnecessarily messy a language becomes. Isn't this one of reasons PHP is despised in some circles? – Ates Goral Feb 17 '09 at 19:43
  • @joe_mucchiello: I agree that my assembly analogy is not a strong argument. I was referring more to the possible origins of those unary operators -- it feels "natural" from an assembly perspective. I wasn't suggesting that C code is compiled that way. – Ates Goral Feb 17 '09 at 19:51
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.

Jeff Yates
  • 61,417
  • 20
  • 137
  • 189
  • I was thinking the same, it would be a nice shorthand. – Chuck Conway Feb 17 '09 at 18:08
  • It would, but I think it mixes up semantics considering the primary usage with Nullable types where it is used to provide a default value in the absence of an actual value, rather than during assignment of a value to an otherwise null variable. – Jeff Yates Feb 17 '09 at 18:09
  • No such guarantee exists. I could += or -= x where x is 0 and I could *= or /= x where x is 1. ??= is no better or worse than ?? itself in terms of syntactic sugar. – jmucchiello Feb 17 '09 at 19:13
  • @joe: I think you missed my point. I stated that in all cases BUT where x is 0. ??= is worse because the value is ONLY modified if the initial value is not null, whereas the modification of the value for += or -= is based on x, not the value receiving assignment. – Jeff Yates Feb 17 '09 at 21:11
  • Therefore, it is more likely that += or -= will result in an assignment than ??= would. ?? is a conditional operator rather than an arithmetic one and as such, it just doesn't fit the pattern used by +=. -=, *=, etc. – Jeff Yates Feb 17 '09 at 21:12
5

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...")

Grant Wagner
  • 25,263
  • 7
  • 54
  • 64
3

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

Colonel Panic
  • 132,665
  • 89
  • 401
  • 465
3

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;
John Rasch
  • 62,489
  • 19
  • 106
  • 139
2

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.

James Curran
  • 101,701
  • 37
  • 181
  • 258
2

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...

Dscoduc
  • 7,714
  • 10
  • 42
  • 48
2

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.

Gabe Moothart
  • 31,211
  • 14
  • 77
  • 99
2

The null-coalescing assignment operator ??= was introduced in C# 8.0

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

kirodge
  • 676
  • 5
  • 23
1

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());
    }
}
Anthony Mastrean
  • 21,850
  • 21
  • 110
  • 188
-2

Because there is no such ??= operator in C#.

Whilst += may seem like two operators represented with different syntax its just one operator.

recursive
  • 83,943
  • 34
  • 151
  • 241
AnthonyWJones
  • 187,081
  • 35
  • 232
  • 306