Hacker Newsnew | past | comments | ask | show | jobs | submit | kensai's commentslogin

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.


> 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.


C# was always better than Java as a language. The strength of Java is the ecosystem, and Java being open source and cross-platform from the beginning.

That used to be the case, but I would argue that C#'s ecosystem is just as competitive now. For our backend tech stack at work, all of our libraries used are open source nugets. Back 15 years ago, paid nugets were definitely more standard.

Language design isn't just about adding every possible feature. For example, someone mentioned operator overloading. As someone who has written a lot of Scala, I think operator overloading would be a very bad feature for an enterprise language like Java which needs to be consistent above all else. I never understood the obsession some people have with the C# vs Java debate anyway. Generally, both languages are very good at what they do, each having its own set of advantages and disadvantages. Regardless, a developer can pick up the other language with basically no effort.

> I think operator overloading would be a very bad feature for an enterprise language like Java which needs to be consistent above all else.

Operator overloading increases consistency. Instead of having

  int a = b + c;
  CustomNumberType x = y.add(z);
you have

  int a = b + c;
  CustomNumberType x = y + z;

Yeah it's bad when it's abused, so don't abuse it.

But not having operator overloading when dealing with vectors is maddening.


The problem with operator overloading is it makes things confusing when mixing types and let's programmers write confusing code.

    Person x;
    Job y;
    CustomType z = x + y;
WTF is Z?

Is the argument, anyway, I support operator overloading.


Java’s planned approach is more like typeclass-style interfaces than unrestricted operator overloading. Types opt into core-defined operator contracts, rather than every library inventing arbitrary meanings for symbols.

> WTF is Z?

Hopefully a type error, because no sane programmer would implement addition like this. Obviously an insane programmer could, but that’s not the fault of operator overloading. The following code is exactly as confusing:

    Person x;
    Job y;
    CustomType z = add(x, y);

I don't know; you can bit shift an output stream by a string (or char array) in C++ (std::cout << "Hello, world!"). That seems pretty mad to me.

Are you trying to imply that Bjarne Stroustrup is a sane programmer?

> WTF is Z?

Take a person, add a job, you get an Employee or EmployedPerson. Person.add(job).

I agree overloading can create footguns, but domain concepts should make a lot of sense in context when basic arithmetic operations are performed on them. Party = Meeting + Booze.

Custom operators are a big assistance for DSLs, and overloading can also aide their creation and elegance. Part of the “awesome but don’t be a jerk about it” toolbox.


Java wasn’t open source at all from the beginning.

And the binaries, the default sdk when using java, i.e. oracle jdk, is still not open source, encumbered with a mine field of legalese. For a long time it also included malware as ask toolbar. Stay away.

No, but it was free/gratis distributed on almost every developer magazine shipping with CDs.

One of the reasons why it took off.


To the point that after all the drama with J++ that lead to .NET and C# development, Microsoft nowadays is also an OpenJDK contributor with their own distributions, and official developer advocacy channels on YouTube, conferences and devblogs.

Turns out they really want to have plenty of Java development on Azure as well.


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

Agreed, async function coloring makes for better structured code because it incentivizes keeping IO code near the edges while having a synchronous core.

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

We are not taking about legacy heavy weight OS/platform threads. But "green" threads managed by the language runtime like Go. Java went the Go/Erlang way.

https://javapro.io/2026/03/05/java-25-and-the-new-age-of-per...

https://docs.oracle.com/en/java/javase/26/core/virtual-threa...


> Clearly legacy heavy weight threads, virtual or not, are not superior.

Associating virtual threads with "legacy heavy weight threads" is a fundamental misunderstanding

> That’s why Swift, Rust and Typescript all chose async/await for concurrency.

And Java chose to join Team Go/Erlang. At the end of the day, async/await is just syntactic sugar for futures/promises, which are essentially a way out of callback hell.

Besides, Rust and Typescript aren't good examples here: a green-thread scheduler (a runtime component) contradicts Rust's philosophy, while Typescript is inherently constrained by Javascript.


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

Link?

It starts with the experiment,

https://github.com/dotnet/runtimelab/issues/2398

Which ended with,

> We have chosen to place the green threads experiment on hold and instead keep improving the existing (async/await) model for developing asynchronous code in .NET. This decision is primarily due to concerns about introducing a new programming model. We can likely provide more value to our users by improving the async model we already have. We will continue to monitor industry trends in this field.

Now three years later we have,

https://github.com/dotnet/core/blob/main/release-notes/11.0/...

> Runtime async is a major runtime feature in .NET 11 that introduces new runtime-level infrastructure for async methods. The goal is to improve tooling and performance for async-heavy codepaths. For more details and to track progress, see the Runtime Async epic issue.


Awesome, thank you!

So it's going to be an internal implementation change -- that is, it generates the MSIL code that's generate when a developer writes async/await code, and won't require changes to how a developer writes async/await code?


Both are, IMO, inferior to Ada's TASK construct.

Hahahha no. lol just no.

It always has.

Only if we ignore that nowadays JVM does a better job at being the CLR, while Microsoft has forgotten what the C means.

more than 10 years ago, yes

More like 25. C# 1.0 already had capabilities Java developers are still dreaming of, like structs / value types, properties and operator overloading. C# 2.0 in 2005 introduced generics, implemented far more competently than Java ever did.

Notice you point out features that were easy to add during the beginning where there was no concern of backward compatibility? Now that java is porting value classes to mainline and we might have them soon, and planned operator overloading through type class, I believe java approach is making careful design choices that are semantically sound, rather than adding features that create edge cases such as boxing invariants in unions like C#.

So you try to say that Java gets to be more semantically sound by making bad choices early on? That does not make sense. Those choices are very difficult fix today and many of them can't be fixed. Say what you want but semantically more sound Java won't be. And the boxing with C# unions can and will be addressed later, this was a deliberate choice by the team to bring unions earlier.

> and many of them can't be fixed... And the boxing with C# unions can and will be addressed later

No, they won't. C# already got itself into a corner with 32 bit arrays and 32 bit spans. And if unions are introduced as reference only that will never be fixed due to binary compatibility requirement.


The new C# unions are not reference-only. The attribute/interface allows implementing custom union types by writing `TryGetValue`-methods instead of a single `object? Value {get;}`. The compiler handles this transparently.

The difference is BDFL or design by committee, a big difference between both ecosystems.

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.


Damn. You're old school. Java’s answer is virtual threads, not async/await. The idea is that most server-side IO can stay in direct style enabling blocking-looking code, cheap virtual threads underneath. So you don’t split the whole codebase into sync vs async functions just to avoid blocking OS threads. CompletableFuture and reactive APIs still exist, but Loom reduces the need to use them as the default application model. You can now launch millions of virtual threads to do IO.

So the em-dashes is the new AI taletell? I mean, I have noticed them, but never thought it was such a characteristic.

New telltale? I mean this in the most polite way but have you been living under a rock? Its been a clear sign people have been more than noticing since at least 4o back in mid 2024.

No offense, but if feels to me the author writes this piece to convince himself. I am afraid he is right. But the bottom line is the same: vibe coding, agenting engineering, everything AI-related comes for our jobs.


Among other things, he is The Dude! ;)


However, even if Ada is amazing and very secure, it could not help avoid at least one airspace disaster, ain't so? https://en.wikipedia.org/wiki/Ariane_flight_V88


That is a strange claim, the Ariane accident was a Systems and really a Requirements flaw.

Arguably with that spec the same could have happened if they used punched cards or Haskell instead of Ada.


Just watch this for some depressive vibes: https://x.com/TechLayoffLover


No posts found.



That's probably for the best, really, prevents you from wasting your time reading lots of AI slop...


Is this based on anything real or just AI-generated slop meant to trigger angry reactions? It doesn't quote any sources for any of the stories, so as far as I can see, they're probably 100% made up...


The lake is not however yours to dictate how others will move along. Imagine if the horse owners decided in such an analogy not to allow cars on the road because they noisy and "totally different experience".

You want a pre-AI experience? Feel free to code without it. It's definitely still doable.


In the town where I grew up in they banned cars and now you are only allowed to ride a horse. So your analogy is actually happening in real life.


And so it begins. First they blame, then they lie, at some point they launch the nuclear warheads to a global armageddon. Sarah Connor was right all along! :3


Kali yuga


They've been lying and gaslighting for a long time now, especially when trying to cover up their own mistakes.


to be fair, they only become more and more like us.


They are improving, though, given the international pressures. I've seen it at least in the organisation I am working (a university hospital).


When you think the article is ending, you get more links for further indulging! Thanks.


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: