Why I Prefer C# to Java (The Language)

The first language I really learned to program in was Java. The first language I actually delivered a product with was C#. It wasn’t hard to move from one to the other, as in most aspects the language was exactly the same. There are some significant differences, though. The most striking difference in my mind is how the C# language has received so many nice little features that just make the code cleaner. You could write Java code in C# if you wanted to, but that would just be plain silly. Here’s a sample of what I’m talking about:

Java and C# both utilize a finally concept that lets the programmer clean up resources. However, C# takes this a step further with the using statement. Here’s the Java way…

Timer timer;
timer = new Timer();
} finally {

…And now the C# way…

using(new Timer.start()){

The using statement will implicitly call the Timer’s Dispose method once the block goes out of scope. The compiler actually generates the same code as the try/finally block, so it’s all just syntactic sugar. But sugar is so sweet.

Next up, we have the new generic Collections namespace in C#. On my current project (Java), we implemented a class called the Finder, which takes a collection and a specification. It uses the specification object(s) to filter the collection like so:

public List getProductsForSale(){
return new Finder(getProducts(),
new ProductsOnSaleSpecification()).find();
public class ProductsOnSaleSpecification(){
public bool isSatisfiedBy(Object obj){
Product p = (Product)obj;
return p.isOnSale();

The Finder abstracts out the looping, while the ProductsOnSaleSpecification tells the Finder which products we’re interested in. It’s pretty sweet, that is until I realized that this is actually built in to C#’s generic collection classes (the following is pseudo-code… Use of generics is implied, but I’m too lazy to html-encode the angle brackets):

public List getProductsForSale(){
return Products.FindAll(IsProductOnSale);
private boolean IsProductOnSale(Product p){
return p.IsOnSale;

It’s worth noting that the C# collection classes have more than just the FindAll concept… You can also call Exists, Find(one), ConvertAll, FindIndex, FindLast, ForEach, Remove, RemoveAll and TrueForAll in much the same way. You can also pass in an anonymous block of code, which is based on .NET’s support of delegates. I’ve written about this in more detail before.

A basic language feature that exists in C# is the notion of a Property, which allows you to present the internal state of an object in a cleaner form than the Java standard of using getters and setters. Again, this is just syntactic sugar, but it’s nice to be able to visually tell whether you’re operating directly on an object’s state. Here’s the Java code and it’s C# equivalent.

public class Dude(){
private int age;
public int getAge(){
return age;
public void setAge(int age){
this.age = age;

public class Dude(){
private int age;
public int Age{
get{ return age; }
set{ age = value; }

My next C# feature isn’t really a feature, and it’s perhaps the most contentious of my points. The feature is the lack of checked exceptions in C#. My current project has very few points in the code where we actually handle exceptions (the Facades, and various points in the UI, but almost nowhere in the Domain). Yet we’re consistently forced by the Java compiler to stick throws ValidationException on almost all of our methods. It quickly just becomes unwanted noise in the code base.

That’s about it for my little comparison. I still have a few more points I could make, specifically around delegates and events in C#, and how stupid it is that the Java foreach statement equivalent only operates on generic lists without needing a cast, but I’ll save those for another post.

4 thoughts on “Why I Prefer C# to Java (The Language)

  1. Simon

    Checked exception isn’t necessarily a bad thing. For example, it could serve as part of the API for a library. The problem you mentioned in our project, on the other hand, is totally a design flaw. ValidationException should absolutely be an UNCHECKED exception!

  2. Jeff Perrin

    Simon, you are right of course. There are good points to checked exceptions. However I’ve yet to hear of anyone in the .NET world complain about lacking them, which says a lot I guess.

  3. Sam Smoot

    I asked the title question at the last Ruby Group I went to. The answer there was ease of deployment.

    In my work the need to explicitly dispose of an object (as opposed to letting the finalizer do the work) using the using() statement is pretty rare. I think excess usage of using() may be a form of premature optimization, but that’s just me. There are some cases such as IO and Database Connections that it’s a good standard to follow, but those should probably be abstracted anyways.

    Properties are actually a sort spot on my list. :-) It’s so very difficult to do lots of cool things when people go around writing non-virtual-by-default Properties for everything. And 99% of the time they’re just getters and setters.

    I read a post by someone much smarter than me once that basically said that if you’ve got a DataTransferObject on your hands, skip the getters/setters and just use Fields. This was in regards to Java by the way. Being a c# guy I instantly cringed at the idea, but those ThoughtWorks guys are generally a pretty smart bunch so I gave it some consideration and realized that… wow… yes, there’s downsides to the idea, but imagine the upsides. *MUCH* less code (even if it is code-genned by Resharper, it’s still ugly and tedious) and it really simplifies reflective magic since you don’t have to decide between a Property that may have unintended side-effects (since you don’t have knowledge of it until runtime), or a private field that requires a reduced security level.

    Sorry for rambling. The point was, if it’s a DTO, use Public Fields. I buy that.

    If it’s not a DTO, then Fields should be shy, and Properties rare, so to be honest the setTimeout(300) vs Timeout = 300 doesn’t really bother me much one way or another.

    The important part is that neither are Ruby when it comes to getters/setters, so it’s just splitting hairs from that perspective. :-)