Here at Realmware Entertainment, we've received numerous questions as to how we've found the transition from Java to C#, and why we decided to do it in the first place. We've therefore decided to post this article about our experiences, to answer these questions publicly.

The transition:

Moving from Java to C# was incredibly easy. Both use pretty much identical syntax, and we feel confident that any good Java programmer can feel very much at ease with C# within a day.

Similarities:

As you probably know, C# is very similar to Java - and the CLI is very similar to the Java virtual machine. Both C# and Java are object-oriented, type-safe languages that normally run under a managed environment. They both provide garbage collection, exception handling, strong typing and multi-threading. In addition, contrary to popular to belief - both are fully cross-platform, merely requring a virtual machine to be written for the underlying platform.

The elegance of Java:

One of the first things we felt in our move from Java to C# is the lack of any major coding conventions. While there certainly are some design guidelines on the MSDN site, they feel a lot more vague and open than Java's clear and concise conventions.

Another thing we missed from Java? Comment documentation. While C# certainly supports this via XML, it's a lot more messy than Java's format, making it much harder to read directly from the source-code - something we commonly do while programming. Here's an example of documentation for a method argument, first in Java and then in C#:

@param toast A slice of buttered toast.
<param name="toast">A slice of buttered toast.</param>

I almost obsess over conventions and design, so these are extremely nice features of Java to me.

The power of C#:

C# has a wealth of extremely useful, intuitive and powerful features that Java doesn't have. In other words, C# is pretty much a more powerful Java. Just take a look at some of the things you get by using C#.

Speed:

In every one of our tests, C# has been faster than Java, usually significantly so.

Properties:

One of the first things you learn in Java are about getters and setters - that is, a huge series of methods named in the getValue and setValue formats, used to regulate the setting and retrieving of private fields. This is an extremely important rule of object-oriented programming. Take a look at the example below:

private Bread toast;

public Bread getToast {
	return toast;
}

public void setToast(Bread toast) {
	if (toast.isBurnt()) return;
	this.toast = toast;
}

// Somewhere else in the program.
plateOne.setToast(plateTwo.getToast());
plateTwo.setToast(null);

C# provides support for this within the language, known as properties. It results in clearer and more intuitive code, as values can be accessed and set as though they were public fields - the getter/setter method calls are still there, but they are hidden from you. Take a look at the example below:

private Bread toast;

public Bread Toast {
	get { return toast; }
	set {
		if (value.Burnt) return;
		toast = value;
	}
}

// Somewhere else in the program.
plateOne.Toast = plateTwo.Toast;
plateTwo.Toast = null;

As you can see, the getter/setter methods are contained in one place, and the code to obtain and assign the field's value is much clearer and intuitive, leading to more productive code! Another thing that's extremely common is the need to have 'empty' getters and setters - that is, ones that don't actually do anything more than a field would do. In large Java programs this would require field/getter/setter code for each field, leading to large and messy code. Again, C# comes to the rescue, with its automatic properties. Take a look:

public Bread Toast { get; set; }

It's as simple as that. You can later define the getter and setter if necessary without breaking other code (as would be the case if you used a public field).

Unsigned data types:

While we are fond of Java for its simplicity, the lack of unsigned types are a major blow to it. These are extremely useful data-types, as often in programming you don't require negative numbers. They provide a large maximum value, not wasting any memory. They are also more intuitive - especially when working with bytes!

Events and delegates:

In Java, it's extremely common to need to implement an interface in order to allow your class to subscribe to events. C# supports events within the language itself, making for more readable and clearer code. Take a look at the example below:

bread.Toasted += MyOnToastedMethod;

Structures:

These are user-defined primitives (value types) that are allocated on the stack, gaining a performance boost. These are most useful for small mathematical types, such as vectors.

Operator overloading:

These can lead to extremely unclear code when used badly, but the exact opposite when used well. Compare for yourself. Here's the Java version:

result = one.Add(Two.Mult(Three.Subtract(Four)));

And here's the C# version:

result = one + two * (three - four);

The C# version is much clearer and more intuitive.

More flexible enumerations:

In Java, enums feel clunky and restricted, and can't even be given proper integer values. This leads to the common solution of using a long list of public static finals (constants) instead, losing all the advantages enums offer. C# lets you assign values to your enums, resolving this issue. You can even specify the underlying data-type. Take a look at the example below:

public enum Toast : ushort {
	Buttered = 0,
	Unbuttered = 1
}

While you don't normally need such functionality (and thus Java enums are great), sometimes you may need to guarantee that an enum will be the same across two entirely separate applications - and C# solves this very nicely.

Pointers:

These can be dangerous and should certainly be used rarely, but when performance is critical or you need to do low-level operations, these can be extremely useful. C# lets you use them, and solves the danger-issue by requiring you to specifically mark your code as unsafe.

Conclusion:

After spending a long time programming in Java and then C#, we've certainly had a while to let the differences set in.

In our opinion, Java is a hand-holding language suitable for beginners and sloppy programmers. That's certainly not to say it's a bad language! It's simply a language that focuses on simplicity, design and providing a small set of features that work well, along with a full set of rules as to how to style your code - which, as long as everyone follows them, ensures that all code is readable by another Java programmer. We feel that Java's simplicity is its forte.

C#, on the other hand, provides access to more risky, but extremely powerful and useful features. It took a lot longer to learn than Java due to all of these features, but every single one of them has come in handy. C# feels more suited to advanced programmers who are confident that they can program correctly - that is, following a set of conventions, using the proper design patterns, and producing clear, maintainable code. Programmers like this could produce programs just as readable as Java (perhaps more so) that are a lot more functional. We feel that C# empowers us to do what we need.

Another thing worth pointing out is that there is currently better cross-platform support for Java, as Sun writes virtual machines for a multitude of platforms. However, this is coming along quickly for C#, with various groups producing open-source cross-platform virtual machines that already support the majority of features.

The final conclusion is that both are extremely capable and elegant languages, with C# boasting features and power, and Java boasting elegance and simplicity. What should you use? Whichever you feel most comfortable with! As for us, we'll be sticking to C# from now on.

Thank you for reading - I hope this article was of interest!

Extra reading:

The C# Language Reference.
The Java Language Reference.
.NET Design Guidelines for Developing Class Libraries
Code Conventions for the Java Programming Language.