Live data from Hacker News

Union types in C# 15

devblogs.microsoft.com

181–190 of 215 posts

Re: Union types in C# 15

#181

Earlier quoted context omitted.

You are looking at it from what you know about C#, the goal is how can you reduce (delete) all this to make the language more accessible. For you it may be fine to write: List strs = new List (); And sure if you have been using C# for years you know all the things going on here. But it shouldn’t be an argument that: List strs = []; Is substentionally easier to grasp. And that has been the theme of all changes. The ex…

One issue I have with all these syntax changes is that they are all just more overhead for one to remember. All for what though? Just to just save a few more keystrokes? I work on multiple applications with different versions of C# and/or Dotnet. I find it quite annoying to have to remember what syntax sugar is allowed in which versions. If C# did not want verbose syntax, then Java was a poor choice to imitate.

C# only exists because Sun did not allow Microsoft to keep using J++.

Without the lawsuit, COM+ Runtime (aka .NET) would have used J++, as originally designed in the Ext-VOS paper.

Re: Union types in C# 15

#182

Boxed. Killed all my excitement.

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.

Re: Union types in C# 15

#183
post #164

Earlier quoted context omitted.

The C# unions as described are discriminated unions. The fact that they flatten a union of optional types into an optional union of the corresponding non-optional types is indeed a weird feature, which I do not like, because I think that a union must preserve the structural hierarchy of the united types, e.g. a union of unions must be different from a union of all types included in the component unions, and the same…

> that a union must preserve the structural hierarchy of the united types, e.g. a union of unions must be different from a union of all types included in the component unions, and the same for a union of optional types, where an optional type is equivalent with a union between the void/null type and the non-optional type This is exactly the difference between simple union types and discriminated unions. This c# featu…

The word "discriminated" by itself does not specify this property.

"Discriminated" just means that at run time you can discriminate the values of a union type by their current type, so you can use them correctly in expressions that expect one of the component types.

I agree that the right implementation of discriminated types is that mentioned by you and which is that of many important programming languages, but even if I disapprove of this property that the C# unions have, which in my opinion may lead to unexpected behavior that can cause subtle bugs, the C# unions are still discriminated unions, where you can discriminate the current type at run-time, with a "switch".

In my opinion, one should avoid this weird behavior of C#, by always defining only unions of non-optional types. Where needed, one should then define an optional type having as base a union type. Then these unions will behave like the discriminated unions of other languages.

Whether you use or not this policy, there are types that the C# unions cannot express, but if you use this policy, at least the limitations become explicit.

Re: Union types in C# 15

#184

Earlier quoted context omitted.

Not OP but I would love to check that out

Sure, as an example: https://github.com/dotnet/csharplang/blob/main/meetings/work... Again, very rough. We go round and round on things. Loving to decompose, debate and determine how we want to tackle all these large and interesting areas :)

Oh I’m very happy to hear this is being worked on!

Re: Union types in C# 15

#185
post #159
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…

Careful not to mix unions with sum types, though. The key distinction is that the latter are disjunct sets, even if you "sum" together the same type twice, you can always tell which "way" you went. An example that may show the difference: if you have a language with nullable types, then you basically have a language with union types like String|Null, where the Null type has a single value called `null` and String can…

> Careful not to mix unions with sum types, though. The key distinction is that the latter are disjunct sets, even if you "sum" together the same type twice, you can always tell which "way" you went.

This is a really good point. I'd love to be able to have a sum type of two strings ("escaped" and "unescaped"); or any two kinds of the same type really, to model two kinds of the same type where one has already passed some sort of validation and the other one hasn't.

Edit to add: I figure what I want is for enums to be extended such that different branches are able to carry different properties.

Edit again (I should learn to think things through before posting. sorry): I suppose it can be faked using a union of different wrapper types, and in fact it might be the best way to do it so then methods can take just one of the types in arguments and maybe even provide different overloads.

Re: Union types in C# 15

#186
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…

I think Zig does a very good illustration of this distinction. They separate:

- enum: essentially just a typed uint tag collection

- union: the plain data structure that can contain any of several types

- tagged union: combines enums and unions, so you can dispatch on its tag to get one of the union types

Read from this section and they appear in order:

https://ziglang.org/documentation/master/#enum

Re: Union types in C# 15

#187
post #167

Earlier quoted context omitted.

The C and Rust union types are extremely sharp blades, enough so that I expect the average Rust beginner doesn't even know Rust has unions (and I assume you were thinking of Rust's enum not union) I've seen exactly one Rust type which is actually a union, and it's a pretty good justification for the existence of this feature, but one isn't really enough. That type is MaybeUninit which is a union of a T and the empty…

In Rust's case, union types should only be used for FFI with a C ABI. As for C, it is a sharp blade on its own.

I do not agree. MaybeUninit is without any doubt more valuable than the C FFI use

I can't even think of any prominent C FFI problems where I'd reach for the union's C representation. Too many languages can't handle that so it seems less useful at an FFI edge.

Re: Union types in C# 15

#188

Boxed. Killed all my excitement.

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.

Re: Union types in C# 15

#190
post #149

Hell yeah! After all these years it's finally here. One thing I miss here (and admittedly I only skimmed through the post so if I missed this, please do correct me) is "ad hoc" unions. It would be great to be able to do something like public Union GetThing()... Without having to declare the union first. Basically OneOf but built-in and more integrated

I guess you can define

  union Union(T1, T2);
Add a bunch of overloads and you'd replicate for T1|T2 syntax the equivalent mess to (Value)Tuple that eventually became the backing for actual tuple syntax.
Post reply on HN