Some of the remaining warts are because it is wedded to the .NET CLR, so if the CLR says you can't do that then, too bad C# can't do that. It would not be practical to do anything about those.
I don’t like that there are 3+ ways of checking if a value is null tho.
We're discussing Windows and all its ad-ware/invasive changes, and someone brings up C# without giving a real explanation or examples.
The last few C# versions brought primary constructors, collection expressions, records(!), tons of Span<T> improvements/support, etc. I just flicked through the list, and nothing that stuck out to me as being bloated.
The main bloat C# has is older stuff that you really shouldn't be using anymore (e.g. ArrayList, dynamic, Thread, delegate keyword, etc).
I brought up C# because the article discusses a Microsoft Windows design philosophy that I feel is also reflected in their approach to C#. It’s a Microsoft thing.
I agree with you that the examples you mention were great additions to the language! But I still think the C# design team has some seriously screwed up priorities. My theory is that this one year cycle they are on is hampering their ability to make changes (like sum types) that require more than a year of work.
I understand that you shouldn’t always give users what they ask for - but this is something that has picked up steam in other languages because it’s actually useful and makes code bases easier to maintain.
I've used C# since 2008 for business software and high performance computing. I've not missed sum types at all. Most of what was added is something I see a lot of value in. I don't like that it, by design, obsoletes some older parts of the language, but that's about it.
I'm now using C# on linux almost exclusively. No complaints from me!
- https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/cs...
- https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/cs...
- https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/cs...
- https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/cs...
- https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/cs...
There is value in a language with minimal syntax like Go, but it's not the only choice. C# is a pretty nice language overall, even with all the warts. But every language people actually use does have ugly stuff somewhere.
All it takes is a method signature like:
Z read<Z>(Func<A,Z> readA, Func<B,Z> readB)
It's a bit of a Yoneda embedding like way of forcing it in to the language, but hey it works.Presumably, you use a function like this to represent your sum type containing the value "avalue":
(readA, readB) => readA(avalue)
The problem I have is that when you create this function you have to reify the return type Z. You can't use this value in arbitrary contexts where the accessors need to return different types.How do you get this to work?
I mean you could return a sum type if you really need to.
Formally a sum type is just something that turns a pair of functions to Z into a single function from the sum type to Z. In fact it shouldn't do more than that.
But when I want to use the value in two different places I don't want Z to be the same in both places.
That's where I'm stuck. When I instantiate the function that represents a value of the sum type I need to choose a return type Z, which is locked in for every use of the value.
I think I understand the idea. I don't see how to make it work in C#.
They continue to fiddle with design approaches to solve this. See https://github.com/dotnet/csharplang/blob/main/meetings/2025...