16 comments

[ 4.7 ms ] story [ 47.2 ms ] thread
C# is a copy of Java.
Many great things are built off the experience of earlier efforts. But I think a point from the discussion is that C# was a huge leap forward and has progressed further and faster than Java. The two languages have been an interesting case-study in two very different ways to design and support a language.
It may have originally started as a copy of Java but its evolution has been quite separate mostly because it made the jump to parametric polymorphism at a point where they could break backwards compatibility and fork the standard library.
Also remember Stroustrop's Law: "There are two types of programming languages. Those that nobody likes, and those that nobody uses."

To my eye Java gets a lot more usage, particularly outside of a single company's ecosystem. Some of that is because of company cultures, like Eric mentioned. Microsoft is all about increasing the value of their platform, while Sun's DNA is about open software systems and ecosystems. But the consequence is that Java is used in a lot of places that are not directly aligned with Sun's software stack or corporate vision, and it grew faster, and had more cooks in the kitchen, and as a result the overall platform is significantly less cohesive.

Sun has ceased to exist a decade ago
The Java team and everyone else that seats at JEP table is largely the same group of people.
Most of the technical decisions that led to the incoherence the article is talking about were made from 1995-2005, when Java was still very much under Sun's control. It's also telling that Java is still very much in use despite being owned by Oracle for the last decade. Would C# have much usage at all if Microsoft went bankrupt?
c# also got 3-5 years of lessons from java -- first release 1996 vs 2001.
Indeed, it's not always language design team's decision to implement e.g not reified generics (Java) / reified generics (C#)

or ship Task<T> as class instead of struct like C#

> or ship Task<T> as class instead of struct like C#

Required reading: https://devblogs.microsoft.com/dotnet/understanding-the-whys...

------

This isn't as-big a problem as you'd think: The CLR has internal magic that will memoize/intern certain common Task<T> results, e.g. `Task<Int32>` for Result values between 0 and 100, for example. And a compiler-generated async method that returns `Task` will use the `static Task.CompletedTask` singleton instance.

While the runtime cost of GC heap allocations is now coming under scrutiny as the current main performance factor, we shouldn't be irrationally averse to Gen 0 allocations on the order of hundreds of objects per second: that's all well-within the means of a computer made in the past 10 years, and when you use a modern concurrent background GC with a CPU with more than a couple of cores (i.e. literally every machine made in the past 7-8 years) it's nothing to worry about.

Remember that a Task<T> is used to represent a relatively expensive operation, such as IO or a background thread job, - and in the course of the computer completing that IO or job it's going to do many things orders-and-orders of magnitude more expensive than allocating a small Gen 0 object for the Task<T>.

There is a struct equivalent of Task<T> as well: ValueTask<T>, which is intended for high-throughput async operations. Of course using ValueTask<T> only makes sense when T itself is also a value-type, and what kind of practical async operations need to return hundreds-of-thousands of value-type values in an async loop? Very, very few, in my estimation. The official guidance I've read is that the people who think they "need" ValueTask<T> probably don't need it.

Also, given that a Task<T> is essentially a mutable view of some linear process it means that Task<T> needs to be a reference-type so the latest state is directly accessible to the Task<T>'s consumers. A value-type obviously cannot do that, which is why ValueTask<T> can only be `await`ed once otherwise it throws.

May be C# somehow “better” than java, but .NET framework is a burning garbage truck from hell. In all terms.
Have you used dotnet core lately? From 3.1 and onwards? The ecosystem (both tools and libraries) is quite nice, and C# is great and getting better (can't wait until built in sum types)

It's honestly one of the most enjoyable developer experiences out there. Almost everything seems well designed and cohesive

Form the thread:

"Eric Lippert @ericlippert · Sep 23 Great point. Sun's strategy for Java has always struck me as weird. They sold expensive hardware, so why build a language whose selling point was that it commoditizes hardware? A write-once-run-anywhere strategy accelerates ability to move off their expensive hardware."

TLDR: In their mind they were commoditizing the OS, not the hardware

I think the reasoning at the time was Microsoft was using the desktop to eat into the server market, while the PC hardware ecosystem was standardizing and commoditizing the hardware. Sun's business structure based on high ticket item sales was in trouble.

They had no chance taking on the desktop OS, so I guess they believed commoditizing the OS on the next layer up was the game to play. Remember their "an OS is just a bag of drivers" spiel?

Once the OS would be abstracted away they could then make hardware specific for the JVM. They started giving out those "Javastations" to university CS labs, where they usually sat collecting dust on top of a cupboard as they had no upside to a "normal" desktop computer and lots of downsides.

So in their vision everything was written in Java, and run on a JVM which made the lowest common abstraction owned by Sun, not Microsoft. It is also why they were so hostile to any attempt at leaking from the abstraction. Java on Windows could not be more functional than Java on other OS'es

My take was that the bright Sun future was near free lightweight Javastations on the desk with datacenters crammed full of expensive Sun hardware (not uncommon in those days) running the "real" computations.

You mean like Android and AWS?