Java vs C# – Part 3


This is the third in a series of posts about the similarities and differences between C# (and .NET, to some extent) and Java. You can find the first one here and the second one here.

Again, with this I do not intent to demonstrate that one is superior to the other – totally – as I really like both platforms, even though I work mostly with C# and .NET. This is merely an exercise to show these differences and maybe it can be useful to someone who is learning one or the other. If you find something that you think is wrong, please let me know!

Keyword Usage

In Java, it is not possible to use reserved words, or keywords, such as class, public, etc, as variables, parameters or field names. In C# you can if you prefix it with @:. For example:

var @class = “My Class”;

Object Class

The Object class is the root of both type hierarchies in both Java and .NET. The two are pretty similar, with some remarkable exceptions. All of the following have exactly identical behavior:

Java .NET
clone MemberwiseClone
getClass GetType
equals Equals
hashCode GetHashCode
finalize Finalize
toString ToString

.NET does not offer methods corresponding to notify, notifyAll or wait. On the other hand, Java does not offer a method like ReferenceEquals.


Recent versions of C# lets us return tuples, which are sets of values combined together ad hoc, but not inside a type definition. For example, should you wish to return a coordinate from a method, you could do this:

(double x, double y) GetCoordinates()


double x = …;

double y = …;

return (x, y);


It is also possible to “deconstruct” a class into a tuple, by providing a proper Deconstruct method:

public class Coordinate


public void Deconstruct(out double x, out double y)


x = …;

y = …;



Coordinate coord = …;

(double x, double y) = coord;

You can have as many Deconstruct methods you like, provided their signatures are different. For now, at least, Java is still lacking this functionality.


C# lets us use the nameof keyword to obtain a strongly-typed name of a class, method, property, field or parameter. It is very useful because it is refactor-friendly: should you change the name of the target, you also change the value that is being assigned. An example:

var className = nameof(MyClass); //”MyClass”

var fieldName = nameof(MyClass.MyField); //”MyField”

Mind you, only the “final” piece is returned, for example, if you use nameof with a fully qualified type name, you’ll only get the type name.

Friend Assemblies

As you know, internal classes and their methods are not available outside the current assembly/namespace. In C#/.NET, however, we can make these internals available to other assemblies by applying the InternalsVisibleToAttribute attribute to the assembly that we want to make available. These are called friend assemblies. For example:



C# 5 introduced a new asynchronous programming model around the async and await keywords. I won’t go into the details of it but essentially it simplifies asynchronous programming a lot, preventing the usage of a lot of boilerplate code. It goes like this:

async Task<int> Compute(int a, int b) { … }

var result = await Compute(1, 2);

Import Methods

In C# we can import public static methods from public classes, which means, we can use them without prefacing them with the name of the class. The syntax is like this:

using static System.Environment;

and the usage:

var path = GetEnvironmentVariable(“PATH”);

Local Functions

.NET allows us to define local functions, that is, functions that exist only in the scope of methods. They are similar to lambda functions, with some remarkable differences, among which:

  • They can have attributes applied to its parameters
  • They can have ref, out and other kind of parameters
  • They can be asynchronous

An example:

void SomeMethod()


int sum(int a, int b) => a + b;

var x = sum(1, 2);


The closest that Java offers is anonymous classes, which are actually pretty cool, IMO.


Java offers the assert keyword as part of the language, this has no equivalent in .NET. An assert evaluates a Boolean condition which, if not found to be true, throws an error:

assert speed < SPEED_OF_LIGHT;

Forgot to say, assertions can be disabled, which means, they are turned into no-ops.

Next Steps

I still have a couple of things to talk about, so be prepared for a future post!

As always, do let me know if you think I got anything wrong or you wish me to clarify something.

Published by

Ricardo Peres

Team Leader at Dixons Carphone. Microsoft MVP.

Leave a Reply

Your email address will not be published. Required fields are marked *