I’m having a hard time imagining where this is useful. If I’m trying to assign to a property, but encounter an intermediate null value in the access chain, just skipping the assignment is almost never going to be what I want to do. I’m going to want to initialize that null value.

Hi there, one of the lang designers here :)

Think of it this way. We already supported these semantics in existing syntax through things like invocations (which are freely allowed to mutate/write). So `x?.SetSomething(e1)`. We want properties to feel and behave similarly to methods (after all, they're just methods under the covers), but these sorts of deviations end up making that not the case.

In this situation, we felt like we were actually reducing concept count by removing yet another way that properties don't compose as well with other language features as something like invocation calls do.

Note: when we make these features we do do an examination of the ecosystem and we can see how useful the feature would be. We also are community continuously with our community and seeing just how desirable such a feature is. This goes beyond just those who participate on the open source design site. But also tons of private partners, as well as tens of thousands of developers participating at our conferences and other events.

This feature had been a continued thorn for many, and we received continuous feedback in the decade since `?.` was introduced about this. We are very cautious on adding features. But in this case, given the continued feedback, positive reception from huge swaths of the ecosystem, minimal costs, lowered complexity, and increased consistency in the language, this felt like a very reasonable change to make.

Thanks!

I'm also not sure I have a lot of code where this would be useful, but adding it to the language I don't feel makes it worse in any way; in fact, it makes it more consistent since you can do conditional null reads and conditional null method invocations (w/ `?.Invoke()`), so why not writes too.

Adding something is always gonna make things worse by default and has to be proven to be useful. Otherwise you have bloat and "yet another way of doing the one thing".

I'm a fan of this notation because it's consistent but language design should not just add features because it doesn't hurt.

I enjoy language features like this too. In fact, I love how languages like C# have handled nullability over the more recent years. No telling how many bugs I have prevented.

The only gripe I have though, is that I have to be remember which version does and does not support such syntax changes. It's not a major issue by any means, but when dealing with legacy applications, I tend to often forget what is and is not syntactically allowed.

“Why not?” is never a good-enough reason to add a new language feature.

If it’s rarely used, people may misinterpret whether the RHS is evaluated or not when the LHS doesn’t exist (I don’t actually know which it is).

Optional operations and missing properties often require subtle consideration of how to handle them. You don’t want to make it too easy to say “whatever”.

> people may misinterpret whether the RHS is evaluated or not when the LHS doesn’t exist

I fully expect no RHS evaluation in that case. I think the fear is misplaced; it's one of those "why can't I do that when I can do this" IMO. If you're concerned, enable the analyzer to forbid it.

There are already some really overly paranoid analyzers in the full normal set that makes me wonder how masochistic one can be...

improving crappy codebases without breaking anything. Bad .NET developers are forever doing null checks because they write weird and unreliable code. So if you have to fix up some pile of rotting code, it can help you slowly iterate towards something more sane over time.

For example in my last gig, the original devs didn't understand typing, so they were forever writing typing code at low levels to check types (with marker interfaces) to basically implement classes outside of the classes. Then of course there was lots of setting of mutable state outside of constructors, so basically null was always in play at any moment at any time.

I would have loved this feature while working for them, but alas; they were still on 4.8.1 and refused to allow me to upgrade the codebase to .net core, so it wouldn't have helped anyway.

These null checks are actually for Optionals in the type system. The whole standard library and many better packages use nullability and thus indicate what can and cannot be null ever. And structs can never be null.

So no, c# are not constantly null-checking more than in Rust

Unfortunately, I suspect this will just makes it easier to keep writing sloppy code.

[deleted]
[deleted]
[deleted]

Monad-maxxing has ruined many a language

This is a functor, not a monad. Also, it's implemented really poorly. If only more languages actually implemented monads well. You wouldn't need special case junk like this.

This is the kind of comment I wish I could print on every sheet of a roll of toilet paper