Yes, this doesn't actually add anything to the "size" of the language, if anything it actually shrinks it. It's existing syntax (the ? and ?? operators) and existing semantics. The only thing was that it worked in half the cases, only reads but not writes. Now this completes the functionality so it works everywhere.

You can argue that C# gets a lot of new features that are hard to keep up with, but I wouldn't agree this is one of them. This actually _reduces_ the "mental size" of C#.

> his actually _reduces_ the "mental size" of C#

IDK, if you read

  Settings?.RetryPolicy = new ExponentialBackoffRetryPolicy();

as "there is a now a ExponentialBackoffRetryPolicy" then you could be caught out when there isn't. That one ? char can be ignored .. unless it can't. It's another case where "just because it compiles and runs doesn't mean that it does the thing".

This to me is another thing to keep track of. i.e. an increase in the size of the mental map needed to understand the code.

The description mentions side effects such as GetNextId(), but creating that object doesn't look like it has any side effects, so perhaps not the best example.

As I wrote in another comment, ignored side effects are perhaps the one questionable aspect of it. I usually assume RHS is evaluated first, regardless of what happens on the left - but I'm not sure that mental model was actually correct. But keeping that would mean having to simply do explicit if _when_ there are side effects. So

    if (myObj is not null)
       myObj.Id = GetNextAvailableId(); // Side effect
But for non-side effects

    Settings?.RetryPolicy = new ExponentialBackoffRetryPolicy();
It's obviously hard to know when there are side effects, but that problem already existed. You could trip this up before too e.g.

    var id = GetNextAvailableId();
    if (myObj is not null)
       myObj.Id = id;
Would have tripped you up. But at least it's obvious WHY it would. Something I have long sought in C# is a good way of tracking what is pure and what isn't.

Hi there! One of the lang designers here.

That's been part and parcel for C# for over 10 years at this point. When we added `?.` originally, it was its nature that it would not execute code that was now unnecessary due to the receiver being null. For example:

    Settings?.SetRetryPolicy(new ExponentialBackoffRetryPolicy());
This would already not run anything on the RHS of the `?.` if `Settings` was null.

So this feature behaves consistently with how the language has always treated this space. Except now it doesn't have an artificial limitation on which 'expression' level it stops at.

I get that the language syntax is now (slightly) more regular.

But also, reading the code will mean keeping track of (slightly) more possible outcomes.

Sure. But that was the case prior to this feature as well. Previously you'd have to store the variable somewhere and null check it. Those could all lead to different outcomes. This just encapsulates that pattern safely in a regular manner. :)