One of my favorite C# features is the null-coalescing operator, which I've used for a long time:
// Simple fallback
var foo = specifiedValue ?? fallbackValue;
// Fetch if not present
foo = foo ?? getAFoo();
// Parameter validation
foo = foo ?? throw new ArgumentNullException(nameof(foo));
// Combination of the two previous examples
foo = foo ?? getAFoo() ?? throw new Exception("Couldn't track down a foo :( ");
I also like the new C# 8 operator that shortens the "fetch if not present" use case:
foo = foo ?? getAFoo(); // null-coalescing
foo ??= getAFoo(); // null-coalescing assignment
I had hoped that perhaps I could use the null-coalescing assignment operator on the parameter validation use case as well, but it seems like it's not allowed. This is what I wanted to do:
foo = foo ?? throw new ArgumentNullException(nameof(foo)); // Does compile
foo ??= throw new ArgumentNullException(nameof(foo)); // Does not compile
Can anyone explain why the null-coalescing assignment operator works on the "fetch if not present" scenario but not on the parameter validation one?
https://dotnetfiddle.net/W8cNPo
I realize that the ... ??= throw ...
thing maybe isn't the most readable way to do this. My question isn't so much about style/readability as it is just trying to understand a quirk of this operator.
Thanks!
A null coalescing operator, in C#, is an operator that is used to check whether the value of a variable is null.
Nullable types work as a connector between a database and C# code to provide a way to transform the nulls to be used in C# code. Null Coalescing operators simplify the way to check for nulls and shorten the C# code when the developer is dealing with nulls.
In cases where a statement could return null, the null-coalescing operator can be used to ensure a reasonable value gets returned. This code returns the name of an item or the default name if the item is null. As you can see, this operator is a handy tool when working with the null-conditional operator.
In certain computer programming languages, the Elvis operator, often written ?: , or or || , is a binary operator that returns its first operand if that operand evaluates to a true value, and otherwise evaluates and returns its second operand.
The answer for ??
is fairly simple. It was simply implemented that way as stated in the documentation:
The null-coalescing operator ?? returns the value of its left-hand operand if it isn't null; otherwise, it evaluates the right-hand operand and returns its result. The ?? operator doesn't evaluate its right-hand operand if the left-hand operand evaluates to non-null.
The answer for ??= throw
is a bit trickier. Seems like it would be useful (or perhaps consistent from a developer perspective) for this to work, but there is a reason. If you dig into the C# 8.0 Null Coalescing Assignment proposal for the ??=
operator, you come across this line (my emphasis added):
Otherwise, the type of a ??= b is A. a ??= b is evaluated at runtime as a ?? (a = b), except that a is only evaluated once.
That means your assignment would evaluate to
foo ?? (foo = throw new ArgumentNullException(nameof(foo)))
which is not syntactically valid.
Did they have to implement it that way? No, they could have implemented it differently, but they did not. The proposal goes on to say this
As with any language feature, we must question whether the additional complexity to the language is repaid in the additional clarity offered to the body of C# programs that would benefit from the feature.
Looks like here, the additional complexity wasn't considered warranted because the alternative is pretty much OK.
Borrowing from Julien's comments on the question (thanks!), the meeting notes provide some more context
Throw expression on the right-hand side
Should the following be allowed: a ??= throw new Exception? throw expressions are only allowed in certain places right now, so we would have to explicitly add support. It makes more sense if the feature is equivalent to a = a ?? b where b is a throw, than a ?? (a = b).
Conclusion
Not supported
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With