Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't you throw in a null-coalescing assignment operator in C#?

Tags:

c#-8.0

Null Coalescing Operator

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 :( ");

Null-Coalescing Assignment Operator

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

Question

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

Disclaimer

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!

like image 809
trademark Avatar asked Apr 29 '21 16:04

trademark


People also ask

What is a null coalescing operator used for?

A null coalescing operator, in C#, is an operator that is used to check whether the value of a variable is null.

What is nullable types and null coalescing operator in C#?

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.

What is null conditional and null coalescing?

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.

What is Elvis operator in C#?

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.


1 Answers

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

like image 180
Kit Avatar answered Nov 03 '22 00:11

Kit