Live data from Hacker News

Union types in C# 15

devblogs.microsoft.com

201–210 of 215 posts

Re: Union types in C# 15

#201
post #106

Hmm, they seem to have chosen to avoid names to the choices in the union, joining C++ variants and (sort of) TypeScript unions: unions are effectively just defined by a collection of types. Other languages have unions with named choices, where each name selects a type and the types are not necessarily all different. Rust, Haskell, Lean4, and even plain C unions are in this category (although plain C unions are not di…

Hi there! One of the C# language designers here, working on unions. We're interesting in both forms! We decided to go with this first as felt there was the most value here, and we could build the named form on top of this. In no way are we thinking the feature is done in C#15. But it's part of our ongoing evolution. If you're interested, i can point you to specs i'm writing that address the area you care about :)

I think it would be a considerable improvement to allow duck-typing over the top. implicitly defined interface that includes exact member matches, something like that.

Re: Union types in C# 15

#202

Earlier quoted context omitted.

You should have kept reading. For performance-sensitive scenarios where case types include value types, libraries can also implement the non-boxing access pattern by adding a HasValue property and TryGetValue methods. This lets the compiler implement pattern matching without boxing.

Still a manual step, pass.

Not necessarily, C#'s incremental source generators mean you could simply slap an attribute onto a class you want to use the non-boxing pattern with, and it'll just generate the pattern for you.

Re: Union types in C# 15

#203

Earlier quoted context omitted.

Hi there! One of the C# language designers here, working on unions. We're interesting in both forms! We decided to go with this first as felt there was the most value here, and we could build the named form on top of this. In no way are we thinking the feature is done in C#15. But it's part of our ongoing evolution. If you're interested, i can point you to specs i'm writing that address the area you care about :)

Hi! Love to see that C# language designers are here on HN :) Just wanted to add just another opinion on a few things. I think many people already mentioned it, but I also don't feel to good about non-boxed unions not being the default. I'd personally like the path of least resistance to lead to not boxing. Having to opt-in like the current preview shows it looks like a PITA that I'd quickly become tired of. Also, ad-…

> I think many people already mentioned it, but I also don't feel to good about non-boxed unions not being the default. I'd personally like the path of least resistance to lead to not boxing. Having to opt-in like the current preview shows it looks like a PITA that I'd quickly become tired of.

The problem is that the only safe way for the compiler to generate non-boxed unions would require non-overlapping fields for most value types.

Specifically the CLR has a hard rule that it must know with certainty where all managed pointers are at all times, so that the GC can update them if it moves the referenced object. This means you can only overlap value types if the locations of all managed pointers line up perfectly. So sure, you can safely overlap "unmanaged" structs (those that recursively don't contain any managed pointers), but even for those, you need to know the size of the largest one.

The big problem with the compiler doing any attempt to overlap value types is that if the value types as defined at compile time may not match the definitions at runtime, especially for types defined in another assembly. A new library version can add more fields. This may mean one unmanaged struct has become too big to fit in the field, or that two types that were previously overlap compatible are not anymore.

Making the C# compiler jump though a bunch of hoops to try to determine if overlapping is safe and even then leaving room for an updated library at runtime to crash the whole things means that the compiler will probably never even try. I guess the primitive numeric types could be special cased, as their size is known and will never change.

Re: Union types in C# 15

#204

Earlier quoted context omitted.

> but sadly it is saddled with the perception that it is Windows-only, which hasn't been true for a decade In my experience it does not work very well outside of the sanctioned Linux distributions. Quirky heisenbugs and nonsensical crashes made it virtually unusable for me on Void. I doubt that's changed in the years that have since passed. > not necessarily a negative, because Windows is a decent OS Is a language ru…

> In my experience it does not work very well outside of the sanctioned Linux distributions. Quirky heisenbugs and nonsensical crashes made it virtually unusable for me on Void. I doubt that's changed in the years that have since passed. It's open source. Did you follow the spirit of Linux to file a bug report of as much sense of the crashes as you could make? Most OSS only supports as many distros as people are will…

> Did you follow the spirit of Linux to file a bug report of as much sense of the crashes as you could make?

No, because the only reason I needed C#/.NET to work was to use an internal tool someone before me had written in C#/.NET. It was not really to explore C# or make it usable. I just threw out the old tool, wrote a new one in scheme so I could do my job, and moved on with my life. I don't particularly care about this spirit of Linux, and Microsoft's tooling being weirdly fragile isn't my problem. I assume they already know this is an architectural issue, hence why they specify supported distributions. On principle I believe solving the architectural issue is what they should be concerned about, rather than making new bandaids.

> Most OSS only supports as many distros as people are willing to test and file accurate bug reports

The problem is that most runtimes and standard libraries don't need to specify a notion of a "supported" distribution. At best, they just refer to platforms with pre-made packages while happily pointing other distributions to the git repo. Even complicated, highly abstract and weird ones don't make this kind of distinction. SWI-Prolog and its myriad of frameworks (which includes a full blown GNU Emacs clone) work out of the box anywhere. GHC and the RTS work flawlessly out of the box.

I understand (even if I don't feel the same way) why a comprehensive abstraction layer like .NET is evangelized. All the same I have to consider that it's a product of a multi-trillion dollar corporation, made to compete with the thing whose marketing tagline is "write once, run anywhere". That only makes the distro dependency stand in an even harsher relief, frankly.

You like .NET? Perfectly fine and valid, and I assume it actually works for you. Just indicating that "cross platform" is contingent on more than kernel and cpu architecture here, which is fairly unusual for this type of software. That's before we get into things like comparisons with ocaml, which I know is miserable on Windows and thus is often considered not really something you'd seriously consider using there. The .NET ecosystem essentially has the same problem outside of Windows where the grain and expectations of the tooling are counter-intuitive to the operating system and usual modus operandi of its users.

Re: Union types in C# 15

#205
post #93

Is this the last of the F# features to be migrated into C#? What a missed opportunity. I think really F# if you combine all of its features, and what it left out, was the way. Pulling them all into C# just makes C# seem like a big bag of stuff, with no direction. F#'s features, and also what it did not included, gave it a style and 'terseness', that still can't really be done in C#. I don't really get it. Was a funct…

Purity is overrated. C# is a kitchen sink language but you need give credit to the language designers. Compared to C++, for example, C# feels feature rich and consistent even though it abandons purity.

That's a very low bar. Any language feels consistent compared to C++.

Re: Union types in C# 15

#206

Earlier quoted context omitted.

As someone who has been coding C# since the pre-generics days, this is the first syntax change which I strongly disagree with. I pretty much love every little bit of syntactic sugar you guys have added to the language. But this? This seems objectively illogical and just straight up ugly. It blows my mind that this is making it into the language, and it makes me worry about the future of C#.

How do you define "objectively illogical" here?

Just guessing here: Putting something at index 0 that has nothing to do with the content.

I tend to agree, but I also didn’t try it.

I also think the 7% number is wrong. 0.5% seems more realistic. It’s just that you are not able to see the majority of the code. Not everything is checked in or on GitHub.

Re: Union types in C# 15

#207

Earlier quoted context omitted.

> In my experience it does not work very well outside of the sanctioned Linux distributions. Quirky heisenbugs and nonsensical crashes made it virtually unusable for me on Void. I doubt that's changed in the years that have since passed. It's open source. Did you follow the spirit of Linux to file a bug report of as much sense of the crashes as you could make? Most OSS only supports as many distros as people are will…

> Did you follow the spirit of Linux to file a bug report of as much sense of the crashes as you could make? No, because the only reason I needed C#/.NET to work was to use an internal tool someone before me had written in C#/.NET. It was not really to explore C# or make it usable. I just threw out the old tool, wrote a new one in scheme so I could do my job, and moved on with my life. I don't particularly care about…

I think there is an architectural problem, but not where you seem to be expecting it to be. I got caught up in some low level distro nonsense+drama from smashing my head against horrors deep in autoconf in automake and got a deep look into the realm of the Distribution Maintainer lifestyle and how much Linux distributions are individual snowflakes despite presumably all being the same OS. As the old joke goes "the only stable ABI on Linux is Win32".

.NET has a huge kitchen sink standard library. Maybe the closer parallel is Python and Python has had periods where it only supported a few named distributions, too. That's not currently the case, but "how the sausage is made" is still a lot grosser than you might expect, with some Distribution Maintainers maintaining entire forks and a lot of the work not done by Python directly. Python is everywhere because it became one of the favorite shell scripting languages of Distribution Maintainers. (Which also exacerbated the Python 2 to 3 migration because entire distros got stuck on 2 while all their shell scripts got rewritten.) (But also if you want to compare Java's cross platform to .NET's I think we need a long digression into how many Java runtimes there are and the strange and subtle incompatibilities of different distro's affiliations to one or another. I also made the mistake of trying to use a Java application as a regular application in my youth of accidentally dealing with deep distro incompatibilities. That was also not fun.)

I get it, you don't have to like .NET. I just think you have an inflated view of what "cross platform" means when it comes to Linux. Linux isn't just one platform. Most things are rebuilt from source constantly because the binary interfaces especially libc's/glibc's under them are constantly shifting like quicksand. See also the messes that are Flatpak and Snap and how much work they've done to try to build around distro incompatibilities (by building increasingly more complex wish-it-were-VMs).

Re: Union types in C# 15

#208
post #21

Is C# a great language trapped in a terrible ecosystem? ie would masses use C# if it existed in another ecosystem? Or is it becoming a ball-of-mud/bad language compared to its contemporaries? (Honest questions. I have never used .NET much. I'm curious)

> terrible ecosystem .NET is a fantastic ecosystem. Has a decent build and dependency system (NuGet, dotnet run/build, declarative builds in XML). Massive standard library, with a consistent and wide focus on correctness, ergonomics, and performance across the board. You can write everything in many languages, all on the same runtime: business logic in C#; hot paths interfacing with native libraries in C++/CLI; shell…

I work with C#/NuGet on windows every day and my experience is entirely the opposite.

The build and dependency systems are an abysmal esoteric, poorly documented mix between csproj files, sln files, random scattered json files, etc.

The standard library in my experience sucks and has all sorts of issues, especially around Uris, DateTimes, etc.

And the ecosystem itself has such a low quality bar, ironically _especially_ with anything made by microsoft. For every nuget package that's well-designed, well-documented, and easy-to-use, there's five which have bugs and undocumented exceptions and poorly-designed APIs.

Re: Union types in C# 15

#209

I don't love OneOrMore It's trying to generalize - we might have exactly one T, fine, or a collection of T, and that's more T... except no, the collection might be zero of them, not at least one and so our type is really "OneOrMoreOrNone" and wow, that's just maybe some T.

I have the same gripe about IsNullOrWhiteSpace which is basically an extension to IsNullOrEmpty, so it really should be named IsNullOrEmptyOrWhiteSpace.

Re: Union types in C# 15

#210

Earlier quoted context omitted.

Hi! Love to see that C# language designers are here on HN :) Just wanted to add just another opinion on a few things. I think many people already mentioned it, but I also don't feel to good about non-boxed unions not being the default. I'd personally like the path of least resistance to lead to not boxing. Having to opt-in like the current preview shows it looks like a PITA that I'd quickly become tired of. Also, ad-…

> Having to opt-in like the current preview shows it looks like a PITA that I'd quickly become tired of. My belief is that we will have a `union struct` just like we have `record` and `record struct`. Where you can simply say you want value-type, non-boxing, behavior by adding the `struct` keyword. This feels very nice to me, and in line with how we've treated other similar types. You'll only have to state this on th…

That actually sounds like a promising idea. Thanks for putting so much thought into this.
Post reply on HN