Live data from Hacker News

Union types in C# 15

devblogs.microsoft.com

121–130 of 215 posts

Re: Union types in C# 15

#121

Earlier quoted context omitted.

In isolation, yes, I agree with you. But in the context of the cornucopia of other "carefully evaluated" features mixed into the melting pot, C# is a nightmare of language identities - a jack of all trades, master of none, choose your dialect language. No thanks.

> C# is a nightmare of language identities - a jack of all trades, master of none, choose your dialect language. I honestly have no idea where you would get this idea from. C# is a pretty opinionated language and it's worst faults all come from version 1.0 where it was mostly a clone of Java. They've been very carefully undoing that for years now. It's a far more comfortable and strict language now than before.

I can see where he's coming from. For example, `dynamic` was initially introduced to support COM interop when Office add-in functionality was introduced. Should I use it in my web API? I can, but I probably shouldn't.

`.ConfigureAwait(bool)` is another where it is relevant, but only in some contexts.

This is precisely because the language itself operates in many runtime scenarios.

Re: Union types in C# 15

#122

Earlier quoted context omitted.

Absolutely agree. Modern C# language design feels very much lacking in vision or direction. It's mostly a bunch of shiny-looking language features being bolted on, all in ways that make the language massively more complex. Just look at this feature: https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/cs... Was this needed? Was this necessary ? It's reusing an existing keyword, fine. It's not hard to understand.…

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.

Re: Union types in C# 15

#123
post #117

Earlier quoted context omitted.

The NonEmptyList in Cats is a product (struct/tuple) type, though; I assume the Haskell version is the same. The type shown in the blog post is a sum (union) type which can contain an empty enumerable, which contradicts the name OneOrMore. The use described for the type in the post (basically a convenience conversion funnel) is different and makes sense in its own right (though it feels like kind of a weak use case).…

Well you are right of course, I just wanted to explain what they wanted to show. Of course the type would be wrong if the second entry in itself is an empty list. I just wanted to explain the reasoning what they tried to accomplish They could’ve done the Either type which would’ve been more correct or maybe EitherT (if the latter is even possible)

I don't think they were trying to accomplish the same thing as the Scala/Haskell version; these are just two completely different things that happen to share a name because the blog post gave the example a name that is confusing when read literally. The purpose of the Cats version is “there is always a head element”. The purpose of the union in the blog post is more like “this can be a collection, but many callers will be thinking of it as a single element, so don't put the burden on them to convert it”. I do think it's a weak case for them in a type theory sense (I would tend to position that kind of implicit conversion elsewhere in the language), but I can also see it being motivating to a large class of developers…

… wait, I've made a different mistake here while trying to explain the difference, haven't I? I was describing it as a sum type, but it's not really a sum type, it's really just set-theoretic union, right?

Which also means OneOrMore is unsound in a different way because it doesn't guarantee that T and IEnumerable are disjoint; OneOrMore initialized from [x] will always return [[x]] from AsEnumerable, won't it? If I'm interpreting the switch expression correctly and the first case predominates, since a list is-an object? I don't have a test setup handy; someone with actual C# experience, please tell me whether that's correct or whether the compiler signals an error here or something…

Re: Union types in C# 15

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

Not sure, but I think C++ actually does allow std::variant with multiple choices using the same type. You might not be able to distinguish between them by type (using get ()), but you can by position (get (), get (), ...)

I think GP is talking about name-of-field access, not index access or name-of-type

Re: Union types in C# 15

#125

Earlier quoted context omitted.

> C# is a nightmare of language identities - a jack of all trades, master of none, choose your dialect language. I honestly have no idea where you would get this idea from. C# is a pretty opinionated language and it's worst faults all come from version 1.0 where it was mostly a clone of Java. They've been very carefully undoing that for years now. It's a far more comfortable and strict language now than before.

I can see where he's coming from. For example, `dynamic` was initially introduced to support COM interop when Office add-in functionality was introduced. Should I use it in my web API? I can, but I probably shouldn't. `.ConfigureAwait(bool)` is another where it is relevant, but only in some contexts. This is precisely because the language itself operates in many runtime scenarios.

I guess that's a good point. I admit haven't used or seen `dynamic` in so long that I completely forgot about it.

But I'm not sure that's really a problem. Does the OP expect everyone to use an entirely different languages every single context? I have web applications and desktop applications that interact with Office that share common code.

Even `dynamic` is pretty nice as far as weird dynamic language features are concerned.

Interestingly enough `.ConfigureAwait(bool)` is entirely the opposite of `dynamic` -- it's not a language feature at all but instead a library call. I could argue that might instead be better as a keyword.

Re: Union types in C# 15

#126

Earlier quoted context omitted.

I can see where he's coming from. For example, `dynamic` was initially introduced to support COM interop when Office add-in functionality was introduced. Should I use it in my web API? I can, but I probably shouldn't. `.ConfigureAwait(bool)` is another where it is relevant, but only in some contexts. This is precisely because the language itself operates in many runtime scenarios.

I guess that's a good point. I admit haven't used or seen `dynamic` in so long that I completely forgot about it. But I'm not sure that's really a problem. Does the OP expect everyone to use an entirely different languages every single context? I have web applications and desktop applications that interact with Office that share common code. Even `dynamic` is pretty nice as far as weird dynamic language features are…

It is a library call, but one that is tied to the behavior of a language feature (async/await).

The reason I bring it up is that it is another one of those things where it matters in some cases depending on what you're doing.

Look at the depths that Toub had to go through to explain when to use it: https://devblogs.microsoft.com/dotnet/configureawait-faq/

David Fowl concludes in the comments:

    > That’s correct, most of ASP.NET Core doesn’t use ConfigureAwait(false) and that was an explicit decision because it was deemed unnecessary. There are places where it is used though, like calls to bootstrap ASP.NET Core (using the host) so that scenarios you mention work. If you were to host ASP.NET Core in a WinForms or WPF application, you would end up calling StartAsync from the UI thread and that would do the right thing and use ConfigureAwait(false) internally. Request processing on the other hand is dispatching to the thread pool so unless some other component explicitly set a SynchronizationContext, requests are running on thread pool threads.
    > 
    > Blazor on the other hand does have a SynchronizationContext when running inside of a Blazor component.
So I bring this up as a case of how supporting multiple platforms and runtime scenarios does indeed add some layer of complexity.

Re: Union types in C# 15

#127
post #31

Earlier quoted context omitted.

Yup, the commercial libraries. That's pretty big. It's nice the standard library has lots of goodies, but I doubt many projects in reality are zero-dependency (The amount of times I hear "the standard lib is great!" seems more to attempt to defend the plethora of commercial libraries, more than anything) The community feels rather insular too? The 9-5 dayjob types with employers who don't understand or embrace open s…

I work with .NET for my day job and my team doesn't use any commercial libraries. I haven't felt limited in any sense by the .NET ecosystem. Nearly everything is open-source, too.

exactly the same experience here

Re: Union types in C# 15

#128

Earlier quoted context omitted.

I guess that's a good point. I admit haven't used or seen `dynamic` in so long that I completely forgot about it. But I'm not sure that's really a problem. Does the OP expect everyone to use an entirely different languages every single context? I have web applications and desktop applications that interact with Office that share common code. Even `dynamic` is pretty nice as far as weird dynamic language features are…

It is a library call, but one that is tied to the behavior of a language feature (async/await). The reason I bring it up is that it is another one of those things where it matters in some cases depending on what you're doing. Look at the depths that Toub had to go through to explain when to use it: https://devblogs.microsoft.com/dotnet/configureawait-faq/ David Fowl concludes in the comments: > That’s correct, most o…

> It is a library call, but one that is tied to the behavior of a language feature (async/await).

This is a good example of C# light-touch on language design. Async/await creates a state machine out of your methods but that's all it does. The language itself delegates entirely to platform/framework for the implementation. You can swap in your own implementation (just as it possible with this union feature)

> So I bring this up as a case of how supporting multiple platforms and runtime scenarios does indeed add some layer of complexity.

I agree that's true. A language that doesn't support multiple platforms and runtime scenarios can, indeed, be simpler. However that doesn't make the task simpler -- now you just have to use different languages entirely with potentially different semantics. If your task is just one platform and one runtime scenario, the mental cost here is still low. You don't actually need to know those other details.

Re: Union types in C# 15

#129

Earlier quoted context omitted.

Yes, but see the section on custom unions* - you can write non-boxing unions/generators. * https://devblogs.microsoft.com/dotnet/csharp-15-union-types/...

Yes, there's a compat-shim in the stdlib/runtime, but not in the language syntax. E.g. it by-definition won't do escape-analysis and optimize discriminated value-types with the first-class keyword.

For now

Re: Union types in C# 15

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

Not sure, but I think C++ actually does allow std::variant with multiple choices using the same type. You might not be able to distinguish between them by type (using get ()), but you can by position (get (), get (), ...)

I haven’t tried this, and I don’t intend to, because visitors and similar won’t work (how could they?) and I don’t want to have to think about which is choice 2 and which is choice 7.
Post reply on HN