Live data from Hacker News

Union types in C# 15

devblogs.microsoft.com

141–150 of 215 posts

Re: Union types in C# 15

#141

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…

I'm 100% on board with the [] syntax. I'm not on board with adding the syntax for passing arguments to the constructor within that syntax. I agree that = [] is perfectly fine syntax. But I would definitely argue that: [with(capacity: values.Length * 2), .. is non-intuitive and unnecessary. What other language is there that has this syntax? Alternatively, is this a natural way of writing this? I wouldn't say so. My ma…

Hi there. Designer of this feature :D

> is non-intuitive and unnecessary.

intuitive is definitely in the eye of the beholder. When people saw:

`HashSet people = [with(StringComparer.CaseInsensitiveComparer), .. group1, group2]`

they found it understandable. And this was also much nicer than what they'd have to write today (which would bring them out of the nice declarative collection-expression space).

Does that make it 'necessary'? Ultimately that's up to the individual. We felt like it was. Not being able to do simple things like this felt like a 'bitter pill'. Customization of collection construction is common (looking in codebases, it shows up about 7% of the time). So having to 'fall out' from the uniform collection-expr system into the much more verbose and clunky forms just for this common enough case felt 'necessary' to us.

>But I feel that there has to be a direction, things have to work together to make a language feel coherent.

I feel like this is conflicting feedback. Collection expressions made the language more coherent. Instead of 7 different ways of doing things (some of which were genuinely not efficient), we gave one uniform way of doing it. That makes things more coherent. Making it so you don't have to drop out of that for something as simple as configuring the collection makes things more coherent.

Re: Union types in C# 15

#142

Earlier quoted context omitted.

> Try teaching someone C# nowadays. Completely impossible. That isn't a reasonable take. Failing to teach a language by enumerating all its features is an indictment of the instructor and not the language.

I guess I overdramatized the situation a bit :) It's a passionate topic for me; as somebody who has been using C# at work for 10 years now, I'm just not happy with the direction the language has been taking. You're right, it's not impossible and in general it's not among the hardest languages to teach. But I would argue, it is heading that way. There are already so many ways to do things in C#. For example, try expla…

> I guess I overdramatized the situation a bit :) It's a passionate topic for me; as somebody who has been using C# at work for 10 years now, I'm just not happy with the direction the language has been taking.

You should come engage with us on this then :)

We do all our design in the open on github. And a lot of us are available to chat and discuss all this stuff in Discord and the like :)

> C# is not using its budget very wisely in my opinion.

I can promise you. Every feature you think are great had similar detractors over the years. Every Single One :)

Re: Union types in C# 15

#143

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 :)

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 :)

Re: Union types in C# 15

#144

I haven't read this in detail but I expect it to be the same kind of sealed type that many other languages have. It doesn't cover ad-hoc unions (on the fly from existing types) that are possible in F# (and not many non-FP languages with TypeScript being the most notable that does).

IME, this is a good thing. The problem with ad-hoc unions is that without discipline, it invariably ends in a mess that is very, very hard to wrap your head around and often requires digging through several layers to understand the source types. In TS codebases with heavy usage of utility types like `Pick`, `Omit`, or ad-hoc return types, it is often exceedingly difficult to know how to correctly work with a shape on…

Yeah, Typescript feels like it had has arrived at the point where someone needs to write “Typescript: the good parts” and explains all of the parts of the language you probably shouldn’t be using.

Re: Union types in C# 15

#145

Looks like it's "just" type-erasure / syntactical sugar. E.g. value types are boxed.

Right, the default boxes into heap, but unions are different. Some languages pack them as a flat struct (tag + payload, no allocation). Here is visual layout if anyone is interested - https://vectree.io/c/memory-layout-tagging-and-payload-overl...

That is not what C# has just added to the language though. These union types so far are just wrappers over an `object` field which gets downcasted.

F# offers actual field sharing for value-type (struct) unions by explicitly sharing field names across cases, which is as far as you can push it on the CLR without extra runtime support.

Re: Union types in C# 15

#146
post #110

Earlier quoted context omitted.

In C#, all instances have a class, so there is already a discriminant, the class itself. In the article, the example with the switch works because it switches on the class of the instance.

Null doesn't. `union(Int?, String?)` will only have 1 type of null, unlike a proper discriminated union.

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 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, but this C# behavior still does not make the C# unions anything else but discriminated unions, even if with a peculiar feature.

Re: Union types in C# 15

#147

Earlier quoted context omitted.

Yes, but that's just the default behavior. You can implement your own non-boxing version for performance critical applications.

Why on earth did they decide boxing by default was a sensible design decision... We have been pushing toward higher performance for years and this is a performance pitfall for unions would are often thought of as being lighter weight than inheritance hierarchies. F# just stores a field-per-case, with the optimization that cases with the same type are unified which is still type safe.

> with the optimization that cases with the same type are unified which is still type safe.

To be clear, this requires explicitly using the same field name as well.

Re: Union types in C# 15

#148

Earlier quoted context omitted.

Unions can be used as a somewhat safer (not safe by any means but safer), more flexible, and less error-prone form of transmute. Notably you can use unions to transmute between a large type and a smaller type. That is essentially the motivation, primarily in the context of FFI where matching C's union behaviour using transmute is tricky and error-prone.

There are rare cases where all attributes of the C union are valid at the same time. Say you have a 32-bit RGBA color value and you want to access the individual 8 bit values. You can make a union of an 32 bit int and a struct that contains 4x 8 bit integers. Also you can manually tag them and get s.th. more like other high level languages. It will just look ugly.

Yes. I once wanted C unions limited to fully mapped type conversions, where any bit pattern in either type is a valid bit pattern in the other. Then you can map two "char" to "int". Even "float". But pointer types must match exactly.

If you want disjoint types, something like Pascal's discriminated variants or Rust's enums is the way to go. It's embarrassing that C never had this.

Many bad design decision in C come from the fact that originally, separate compilation was really dumb, so the compiler would fit in small machines.

Re: Union types in C# 15

#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

Re: Union types in C# 15

#150

Earlier quoted context omitted.

> Pulling them all into C# just makes C# seem like a big bag of stuff, with no direction. Agreed. Java is on the same trail.

Care to elaborate? I think Java is showing remarkable vision and cohesion in their roadmap. Their released features are forward compatible and integrate nicely into existing syntax. I work much with C# these days and wish C# had as cohesive a syntax story. It often feels like "island of special syntax that makes you fall of a cliff".

It's honestly hilarious since the person you're replying to has heavily advocated Manifold which is a compiler extension to Java that adds every little feature to the language.

https://github.com/manifold-systems/manifold

Post reply on HN