Cute, but is this actually needed? It's one more thing to remember, one more thing to know the subtleties of, and for what? To save writing a very readable and unambiguous line of code?
It feels like the C# designers have a hard time saying "no" to ideas coming their way. It's one of my biggest annoyances with this otherwise nice language. At this point, C# has over 120 keywords (incl. contextual ones) [0]. This is almost twice as much as Java (68) [1], and 5 times as much as Go (25) [2]. And for what? We're trading brevity for complexity.
[0]: https://learn.microsoft.com/en-us/dotnet/csharp/language-ref... keywords/
> Cute, but is this actually needed? It's one more thing to remember, one more thing to know the subtleties of, and for what?
Hi there! C# language designer here :-)
In this case, it's more that this feature made the language more uniform. We've had `?.` for more than 10 years now, and it worked properly for most expressions except assignment.
During that time we got a large amount of feedback from users asking for this, and we commonly ran into it ourselves. At a language and impl level, these were both very easy to add in, so this was a low cost Qol feature that just made things nicer and more consistent.
> It feels like the C# designers have a hard time saying "no" to ideas coming their way.
We say no to more than 99% of requests.
> We're trading brevity for complexity
There's no new keyword here. And this makes usage and processing of `?.` more uniform and consistent. Imo, that is a good thing. You have less complexity that way.
Thank you for all the hard work on C#! I’ve been loving the past 5 years of developments and don’t agree with the parent comment here.
p.s. I will take the opportunity to say that I dream of the day when C# gets bounded sum types with compiler enforced exhaustive pattern matching. It feels like we are soooo close with records and switch expression, but just missing one or two pieces to make it work.
Thanks @klysm! I think we're getting close to that. `unions` are a big part of this discussion, and we're working very hard to hopefully get them in soon :)
I can’t wait! I’ll be frothing at the mouth when that lands
Thanks for the reply and for your work on C#.
I should have been clearer in my message. This specific feature is nice, and the semantics are straightforward. My message is more about some the myriad of other language features with questionable benefits. There's simply more and more "stuff" in the language and a growing number of ways to write the same logic but often with subtle semantic differences between each variant. There are just too many different, often overlapping, concepts. The number of keywords is a symptom of that.
I stumbled over this a few times, mostly when cleaning up older code. This basically just means that using the ?. member access no longer dictates what is possible on the right side.
Property reads were fine before (returning null if a part of the chain was null), method invocations were fine (either returning null or just being a no-op if a part of the chain was null). But assignments were not, despite syntactically every ?. being basically an if statement, preventing the right side from executing if the left side is null (yes, that includes side-effects from nested expressions, like arguments to invocations).
So this is not exactly a new feature, it just removes a gotcha from an old one and ensures we can use ?. in more places where it previously may have been useful, but could not be used legally due to syntax reasons.
I don't get this argument as it really doesn't match my practical experience. Using new C# features, the code I write is both easier to read and easier to write. On top of that it's less error prone.
C# is also much more flexible than languages you compared it to. In bunch of scenarios where you would need to add a second language to the stack, you could with C# still use just one language, which reduces complexity significantly.
> is this actually needed
Yes, actually. I did write it multiple times naturally only to realize it was not supported yet. The pattern is very intuitive.
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
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
But for non-side effects 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. 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:
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. :)
Nothing is stopping you from constraining the language version you want to be used in your projects:
https://learn.microsoft.com/en-us/dotnet/csharp/language-ref...
You can force it all the way down to ISO-1/2.
If this is still insufficient, then I question what your goals actually are. Other people using newer versions of C# on their projects shouldn't be a concern of yours.
Oddly antagonistic take on a reasonable comment. GP could be working together with other people, for example, in which case every such idiosyncratic configuration introduces a little social and mental friction. This is covered at length in similar conversations in Go threads, where people say things like “defaults matter”.
Obviously you’re not alone to disagree, and there are even some good arguments you could potentially be making. But to say “I question what your motives really are” and tell someone what they should be concerned with is… odd?
It’s a very common position with ample practical examples. While there certainly are valid counter arguments, they are a little more involved than “nothing is stopping you.” There is. Collaborating with others, for example.
Easily said, applies to complaints in other languages as well, this is only doable for people that work alone.
Agreed, it appears that since they changed to early release their have become pressured to add new language features every year.
As polyglot I have the advantage that I don't have to sell myself as XYZ Developer, and increasingly I don't think C# (the language itself) is going into the direction that I would like, for that complexity I rather keep using C++.
Just wait for when extension everything, plus whatever design union types/ADT end up having, and then what, are they going to add on top to justify the team size, and yearly releases?
Despite my opinion on Go's design, I think the .NET team should take a lesson out of them, and focus on improving the AOT story, runtime performance, and leave the language alone, other than when needed to support those points.
Also bring VB, F# and C++/CLI along, this doesn't not have to be C# Language Runtime, where it gets all the features of what designed as a polyglot VM.
I went to the .NET Developer Conference (NDC) in London at the beginning of the year. Mads Torgersen (Lead C# Designer, for anyone not in the know) gave a talk about some new proposed features. After describing a proposal to introduce new syntax to make defining extension methods easier, he asked if anyone had any questions. I asked a question along the lines of:
"I understand we sometimes need to address deficiencies in a language, but when we do stop? More syntax is leading to daily decision fatigue where it's difficult to justify one approach over another. I don't want C# to become C++."
It was interesting listening to the discussion that took over from that. The audience seemed in favour of what I said, and someone else in the audience proposed a rolling cut-off to deprecate older features after X years. It sounded very much like Mads had that discussion internally, but Microsoft weren't in favour. I understand why, but the increasing complexity of the language isn't going to help any of us long-term.
Life quality upgrade - needed? Depends.