Live data from Hacker News

.NET (OK, C#) finally gets union types

andrewlock.net

231–240 of 300 posts

Re: .NET (OK, C#) finally gets union types

#231
post #108
post #31

I love C# and in every iteration we're getting more and more features to get C-like performance in a lot of scenarios. C# does it really well because if your problem isn't performance/memory-constrained, you can ignore these features and fallback on the language's natural ease of use.

Do you think by now C# has left Java behind in features and performance?

Speaking as somebody that spent 2yrs as a full-time Java dev before returning to the Microsoft stack: yes.

Java’s Optional sucks compared to how C# (and Kotlin) implement support for nullable types. C#’s async/await syntax is better than… however the hell Java says to implement asynchronous calls now (Thread? CompletableFuture? idk, I never figured it out). ffs, Java doesn’t even have support for string templates yet — they added it as a JDK preview feature (JDK 21?) and then removed it before final release.

Re: .NET (OK, C#) finally gets union types

#232
post #215

Earlier quoted context omitted.

Clearly legacy heavy weight threads, virtual or not, are not superior. That’s why Swift, Rust and Typescript all chose async/await for concurrency.

Except one of the milestones for .NET 11 is to offer similar mechanisms for async/await.

Link?

Re: .NET (OK, C#) finally gets union types

#233
post #108
post #31

I love C# and in every iteration we're getting more and more features to get C-like performance in a lot of scenarios. C# does it really well because if your problem isn't performance/memory-constrained, you can ignore these features and fallback on the language's natural ease of use.

Do you think by now C# has left Java behind in features and performance?

I never liked the C#/Java comparison - Java was designed as a much higher level language, and allows reasoning about low level abstractions a lot less, while doing a ton more optimization in the JIT.

For example, GC escape analysis, automatic lock elision, devirtualization, tiered compilation are fairly recent features in C#, and likely not as mature/powerful.

Or C# has generic specialization, so if your generic param is a stuct, you get a separate implementation, while Java generics work via type deletion.

But in C# you have a ton more synchronization primitives, value types, methods are non-virtual by default etc.

This usually means that expertly crafted C# code can be faster than Java (and more importantly, you can trust the compiler to do the right thing), while if you wrote it exactly like Java, you'd probably end up with slower code.

Re: .NET (OK, C#) finally gets union types

#234

Earlier quoted context omitted.

Not OP here - but for me it’s the open source ecosystem. Java just wins in terms of scope, scale, and stability. I love C# the language, but the ecosystem is a ghetto.

I see this reason a lot but what are some actual examples of what is lacking in the .NET ecosystem vs. Java?

Support for OpenAPI 3.1 in .NET sucks. Up until recently, a third-party library (Swashbuckle) has been the heavyweight, but lagged for years in supporting new features & fixing old bugs. Microsoft created a first party option (Microsoft.AspNetCore.OpenApi) that supports 3.1, but it’s nowhere near feature parity with Swashbuckle yet.

I also find serialization/deserialization to be weak in .NET. Third-party Newtonsoft was king for years, then Microsoft released System.Text.Json. Years later, it lacks feature parity, including an easy way to debug like Newtonsoft did.

Re: .NET (OK, C#) finally gets union types

#235

Earlier quoted context omitted.

Java Virtual Threads are a superior paradigm to C#'s async/await and function coloring.

I don't get what the big problem is with function coloring. You basically only need async when doing IO, and you had better know when a function does it, or you may have a bad surprise at some point in the future.

That! Okay, in 2026 this could be a LSP feature with some editor fanciness but this is a real benefit. My nitpick is that we do not have a depreciation on the non async ones

Re: .NET (OK, C#) finally gets union types

#237
post #209
post #195

Earlier quoted context omitted.

I know. I literally gave the example of a Python Literal in the post you're replying to. TS too. :) My overall point is that Haskell's type system is sufficiently expressive (you may not have "A" | "B" | "C", but you do have A | B | C) that there's no obvious remaining use case for string literals, unless you're thinking of typing input by way of expected literals instead of actually parsing it, which is... a choice.…

By Haskell's type system do you mean with all the GHC extensions? Because TypeScript has structural sub-typing, while standard Haskell (eg. `A | B | C`) has neither subtyping nor structural typing, which both are very useful features for safe "integration/glue" type of programs. (String) literals form a fundamental part of the TS "row polymorphism" (record types) and eg. tuple union type implementation. You can type…

> By Haskell's type system do you mean with all the GHC extensions?

No? What extensions does `A | B | C` require?

> Haskell has neither subtyping nor structural typing

Is subtyping back in? Good news for Java and C++.

Re structural typing, I would ask what behaviour you're after, specifically. For example, this is a valid, typed Haskell function for any two values that can be added, including any user-defined ones:

    adder a b = a + b
If by structural typing you mean silently coercing types that the compiler deems structurally equivalent, then no, but I don't think many people writing Haskell would consider that desirable. A `Person` may have an age (40) and a `Wine` may have an age (2005), but you're not going to get sensible results if you start adding those two together, and your compiler should probably stop you.

Structural typing is the sort of thing that is very valuable if you're bolting a type system onto a language with a cornucopia of untyped structs, like JS objects. It is comparatively much less valuable if you're working in a typed ecosystem to begin with, since you're not liable to have loose untyped structs floating around that require coercion.

> "integration/glue" type of programs

It does sound a lot like you're using string literals in lieu of parsing foreign input, which strikes me as a pretty bad idea. Particularly in a language like TS, which is not type safe at runtime, and which will happily ingest an unexpected value, silently coerce it in all sorts of fun and wacky ways, and cause behaviour far removed from what any static analysis of the TS source would suggest.

> You can type a non-empty array that starts with zero

Can you please name me any possible actual use for this? Especially given the type doesn't even exist at runtime and will never be enforced on input data, so this is a once-off check for comptime constants?

Re: .NET (OK, C#) finally gets union types

#239

Earlier quoted context omitted.

Is it called "trio" state because 3 of the 5 states are not supported? I also like how True is -1. Beautiful all around!

note CTrue, the one true true

CTRUE IS A FALSE PROPHET AND ITS WORSHIPPERS SHALL BURN FOR THEIR HERESY

Re: .NET (OK, C#) finally gets union types

#240
post #108

Earlier quoted context omitted.

Do you think by now C# has left Java behind in features and performance?

I never liked the C#/Java comparison - Java was designed as a much higher level language, and allows reasoning about low level abstractions a lot less, while doing a ton more optimization in the JIT. For example, GC escape analysis, automatic lock elision, devirtualization, tiered compilation are fairly recent features in C#, and likely not as mature/powerful. Or C# has generic specialization, so if your generic para…

> while if you wrote it exactly like Java, you'd probably end up with slower code.

That's not the case for some time already, at worst you get similar performance with Java and with a little effort you can get significantly better performance.

Post reply on HN