My Experience with C# as a Java Guy!
So, the age-old question, Java vs. ‘fill in the blank’. If you are a java developer (sorry Engineer), then you love Java, and you spend time arguing with co-workers about why Java is better or at least not worse than their language of choice. These arguments never end, and will never end, that’s because there are so many languages out there and every month some new language is created which is claimed to be the solution to all our problems.
Does it really matter?
Well, yes and no, and that’s my opinion of course. So we all know turing completeness is a low bar, no need to bring up computability and the turing tarpit. Furthermore, It’s not a question of whether something can’t be solved in a specific language; rather it’s a question of style, preference, readability, maintainability, etc. It’s also a matter of experience and what we are used to along with the eco system each language belongs to. So I’m not going to argue philosophical questions here and I’m just going to focus on my experience of writing code in C# after having years of experience with Java.
So why did I switch to C#?
The answer to that question is, I didn’t. I took a job with company which has historically been working with .NET and C# and their entire backend micro services platform is built around that architecture. Everything they have runs on Windows Server and they use SQL Server for their database needs. But, they came to their senses eventually (this is the Java guy in me bursting out) and realized the shortcomings of the closed platform and looked to alternatives. Java seems to be gold standard in business applications today. So they brought on a few people to help them move to Java and Linux. However, hundreds of thousands or even millions of lines of code are difficult to switch to a new language over night so yes I had to support a lot of the legacy C# code.
As you may imagine I cringed at the idea of having to write C# code. Microsoft is evil, that’s been drilled into my brain from the genesis. However, that was my task, I took it and ran with it. I was pleasantly surprised to say the least.
We all know Java is verbose,
And we always knew it, but when I stated writing production C# code that really came into light. A simple concept like C# Properties reduces boilerplate code significantly. Take for example a simple POJO. We are encouraged to write code with private access modifiers by the basic object oriented principles. That means we need getters and setters. For a simple POJO with one class variable that means at least 9 lines of code:
Now, in C# this is a lot less verbose:
public class A {
public Object obj {get; set;}
}
So that’s 3 times less code than Java, and all I’m talking about here is just a simple data objects. Already, C# is already 60% less verbose, that’s a pretty good start.
There are libraries out there such as, Project Lombok, which allow you to annotate your POJO with @Data annotation and will generate all the boiler plate code at compile time basically making my argument above invalid. I am however talking about pure language features and as far as core Java goes, it’s verbose.
Lambdas
Java 8 has lambdas finally, but have you tried using them? And I don’t mean putting lambdas into the new collections API, I mean defining your own lambdas for your own classes. If you have you know it’s a pain, if you haven’t well, it’s a pain. In C# lambdas have been around for a long time and defining one is as simple as either using the Func<,> or Action<,> interfaces.
However, that’s not what impressed me the most about C# lambdas, are closures which capture the state of all scoped variables as a reference. You see in Java, the closure only gets access to final or implicitly final variables in the lambda context, while in C# you get access to any reference or even primitive in the closure, which mean lambdas are very powerful, leading to a prolific use of functional style programming in this imperative language. Of course a purist functional programmer is going to complain and say that you aren't supposed to mutate state in functional programming and I will have to somewhat agree. However, when careful enough mutating state can come with powerful optimizations. I do have to point out, that lambdas have their place, and overuse can lead to a very unreadable code, but proper use creates very clean code.
Extensions
This is one of my favorite constructs of the C# language. It allows you to extend any object, from any 3rd party library with extra methods. This is extremely powerful, and much of the collections libraries, including LINQ in core C# are using this construct extensively. Imagine if you have an object, to which you don’t have access, or maybe you do, but you don’t want to change the type definition, however you need to add a method, which will make much cleaner code. For example you have some type A and it has many different states, and in order to determine if the state of some instance of A is a success it requires to check multiple states and possibly execute much logic. You can either run this logic every time you need to get the success state, which in my opinion is ugly, or you can create an extension method to type A and hide this ugly logic, then access the success state by simply calling the extension method:
A a = new A();
a.Success(); //via extensions
Implicit Conversions
If you thought Extensions were awesome, Implicit Conversions will blow your mind. Scala takes this to a whole new level and is much more powerful than C#’s version and yet Java doesn’t have anything that comes even close. With implicit conversions you can define the logic to convert an instance of one type into an instance of another type and use this conversion via simple cast. For example, if you have type A and you define an implicit conversion into type B, and lets imagine for minute that this conversion is nasty. This logic resides in type A’s definition, then all you need to do is a simple cast:
A a = new A();
B b = (B) a;
This makes for such clean code; the necessary ugliness is completely hidden away. I really wish Java had this type of construct; it would significantly reduce the already significant verbosity of the language. With Scala (and I’m sure other modern languages) implicit conversion is actually performed by compiler so you don’t even need to do a cast, and you can define the “conversion” anywhere within the scope of your Type. The compiler is advanced enough to find an available implicit conversion and apply to an operation well, implicitly. C#’s version of conversions isn’t as powerful but definitely a step in the right direction.
There are many other useful features in this language, and many libraries, which make life easier. LINQ is just beautiful. It’s built around the Monad/Monoid pattern, which is extremely difficult to understand but the beautiful thing about it, you don’t really need to know anything about Monads in order to use LINQ. This amazing library allows you to write query code to query absolutely anything you want (given there is an implementation) For example, you can query SQL, Mongo, Collections, basically anything that can be expressed as an IEnumerable interface. It’s super powerful, readable and light-years more flexible and advanced than anything Java has to offer at this moment.
String Interpolation
Latest version of C# comes with String interpolation that allows one to very compactly build a string with variables placed (interpolated) directly in the string definition. For example, if you have a variable A you can create string like so: $"I have a variable {A}". In previous versions you had to resort to using string.Format() with placeholders, which is a similar approach Java takes with printf. Interpolation is just clean, nothing else I can really say.
Null Conditional Operator
Another great feature of C# 6.0 is the null conditional operator that also allows one to write compact code. Instead of doing a null check before accessing a field of an object in C# you can use the following pattern:
var obj= new MyType();
var field = myType?.someField;
Here the ? is the null conditional operator which basically works like a traditional null check. If the obj is actually null then field will be null. Otherwise field will get the value of myType.someField. This is a super clean and compact way to write safe operations avoiding null pointer exceptions.
Cons?
I promise you this is not an advertisement for C# and I am not here trying to convert Java developers to use C#, I’m just pointing out the useful features in C# that don’t have parallels in Java. The most significant con however, is that it’s developed by Microsoft! You have to use Visual Studio, which in opinion is garbage. It’s slow, it’s bloated, and it has more features that nobody uses than any other IDE I can think of. Debugging is garbage; I have experienced so many instances where the background thread that handles symbol lookup and management during debugging, timed out after some period because IDE took too long thus rendering the debugging session useless. I have spent more time fighting Visual Studio and restarting it, just to get it to work properly than writing code. Of course that’s a gross exaggeration, but my point is, Visual Studio lags in speed and simplicity behind Intellij and even Eclipse.
Then there is IIS. Most of development that I did with C# is for web applications, and thus I was stuck in the IIS ecosystem. I’m not even going to go into detail about how much IIS bothered me. It’s old, it’s bloated, it’s just so different and in my opinion should be just thrown out and rebuilt using modern principles.
If C# could run natively on Linux and could be run without IIS for web application, this language would not be losing so many followers. Yes, I am aware of mono and yes I am aware that you can use other editors for C# besides Visual Studio, and technically you can run C# via mono without ISS, but I’m not talking about Mono here, that’s a different beast and maybe a different article will cover my experience with it one day.
All in all, I still love Java, I just wish the language designers at Oracle would just finally create Java 2.0, forget about backwards compatibility with billions of Java lines of code already in existence and would introduce modern constructs that C# and other modern languages already come with.
Some of you may argue that Scala is the modern Java and so there is no need for Java 2.0, I will argue that position. I believe if Scala were to be written on top Java 2.0 it would be much more robust and would attract a much wide audience than it does snow.
Final thought: Microsoft has been going through a bit of an internal reconstruction and has been moving parts of the .NET framework into open source world, even made it runnable on Linux. It’s not all there yet, just the core, but it’s a start. In a years time I believe C# and .NET will be fully compatible with Linux and it may become a very different platform. Until then, I’ll stick with Java.
[Edit]
So a few people have been complaining that I talk about the fact C# and .NET is a closed system, not cross platform compatible and I seem to ignore the elephant in the room.. .NET Core. Well, I'm not ignoring it, I have definitely been following the news and have spent quite a bit of time researching the new platform. Yes, it's cross platform, yes it runs on *nix, yes Visual Studio Code is lightweight and kind of awesome. Oh and with the Ketsrel server, IIS goes away for good (and I wouldn't even look back to wave goodbye). Finally you get to use a modern lightweight stack, even if you have to run Nginx as a reverse proxy in front of it.
However, the platform isn't ready yet in my opinion. A lot of types are not supported in .NET Core that are heavily used throughout .NET 4.6 applications, which makes porting applications to the cross platform framework difficult. Additionally, the community needs to catch up. Popular libraries like Log4Net need to natively support .NET Core applications. And that's just one example, there are tons of such packages that simply do not have .NET Core targeted nuget versions. You can't expect a platform to be production ready without the eco system.
In my particular case, in order to port the application into the new platform it would take a major re-write effort. I wouldn't say a complete ground up re-write since probably 85% of the existing code is compatible with the new framework.
Finally
Having said all that, I will say that I was very impressed by .NET Core and ASP.NET Core and have actually started a massive effort of porting my application over. It won't be a simple task and likely I would need to wait until .NET Core 2.0 before I would be able to fully port all my code.