Language Smackdown: Java vs. C#
A pithy quote:
There are only two kinds of languages: the ones people complain about and the ones nobody uses.
Now you might say that's exactly what the creator of C++ would say to cover his tracks. But the point is that Java and C# are languages that are 20 to 25 years old, widely used (maybe 15 million users between them), and are both cursed with toxic corporate associations. When Java first came along it was cool, if a programming language ever could be. But this was because the only Java code in the wild was neat little animations and things like that. As soon as it became widely used for boring line-of-business apps, it began to be thought of as the new COBOL.
Unfortunate Bifurcations
Although this is going to seem like a series of picky complaints about C#, really it's about how any language has to evolve, and is a compromise between past and future, and the whole thing is quite difficult.
Also some speculation on what the future of language interoperability will be.
The kind of problem I'm going to pick on is where languages separate two concepts and treat them differently, making a virtue of the differences, but then it becomes a pain dealing with them generically. The language designers seem to be saying "You shouldn't need to treat these two things the same; they're fundamentally different. You're doing it all wrong!" And yet…
Factory Injection in C#
Update - There was a nasty bug in the original version of this post! Where I previously registered the factories with AddSingleton
, I now use AddTransient
, and I call out the reason for this below.
The modern C# ecosystem (based on dotnet core, due to become .NET 5) enjoys a standard dependency injection system that is, despite its minimalism, is pretty much all you need.
In some ways the ideal dependency injection system is nothing at all: isolate your components by writing an interface/class pair, and make each class accept interfaces to give it access to whatever services it needs. Very often the sole reason for the existence of the interface to go with each class is so that it can be mocked out in unit tests for classes that depend on it. (It's worth noting that in languages based on dynamically typed runtimes there is typically no need to do this - it's especially irksome to see this pattern being imported unnecessarily into TypeScript, where every class is already an interface.)
Hangfire - A Tale of Several Queues
If you've used Hangfire you know it's a really quick and easy way to give your app a queue of durable background jobs, with automatic retrying and a very nifty dashboard to let you see what's happening right now. Jobs can trigger further jobs and so a complex series of processing stages can be decoupled and spill out into a queue of little units of work.
You can setup one database (such as Redis) to store the state of all your jobs, and then multiple identical workers can attach to that database and munch through the jobs, taking them through the lifecycle:
[Enqueued] -> [Processing] -> [Finished]
Eventless - XAML Flavoured
About four years ago, being so taken with data modeling approach used in Knockout.js, I wanted to recreate it for C#. At the time I wasn't actively using C# so I never got to really use it and left it alone.
But in the last year and a half I've written a few view models for a WPF application. The first time I did it I couldn't believe how primitive and laborious it was in comparison. So I started idly messing with Eventless in my spare time - mostly deleting stuff - to make it XAML-friendly.
Just like Knockout, and now MobX, it makes the process delightfully simple. You just declare stuff and it works!
A new kind of managed lvalue pointer
It's already the evening and I haven't yet added anything to the C# compiler today, so here goes!
Properties have special support in C#, but they are not "first class". You can't get a reference to a property and pass it around as a value. Methods are
much better served in this regard: delegates are a way to treat a method as a value. But they are just objects with an Invoke
method.
So all we need is an interface with a Value
property. Objects supporting that interface can represent a single property that can be passed around like any other value:
Using pointer syntax as a shorthand for IEnumerable
Another quickie extension to C#. In the current language, a type declaration T!
is shorthand for Nullable
.
But equally important in modern C# programs are sequences of values, so a similar shorthand for IEnumerable
would be ideal.
The asterisk symbol is underused (you can suffix a type with asterisk to make a pointer, but only in unsafe contexts), and
this was the choice made by the intriguing research language Cω
that influenced LINQ, so let's copy that:
Adding crazily powerful operator overloading to C# 6
I'm going to show you how to enable a new kind of operator overloading by adding exactly four (4) lines of code to a single file in the C# 6 compiler preview. Yes, I was surprised too!
After seeing the video of Anders Hejlsberg showing how easy it is to hack the new open source C# compiler, I had to give it a try.
My aim was (I assumed) a lot more ambitious and crazy than his demo. I thought it would take ages to figure out. But it was still tempting to aim high and actually implement a substantial new feature, because there are a few I've been wondering about over the years.