Wayetender

Member

Blog Archive

Blog

Why You Should Use C# Over Java 0 Comments

C# is better than Java, as a language. For a long time I have kept quiet because of Java's dominance in academia, industry, and coders' minds. Well, I have been moved to spread the gospel of C# now. My reasoning will be objective and technical (although some of the features are just personal preference). If you aren't a programmer, none of this will be interesting to you. If you've never heard of C# (but use Java), then you should check it out after reading this blog. By the end of this, you should be totally excited to use C# in all of your future applications.

Note: I'm including C# 4.0 features in this comparison.

Let me begin with C#'s weak points. It's developed with Windows in mind. New features that are added (like DLINQ, which only had initial support for MSSQL databases) usually are for Windows-based products (see: COM). Also, there's that little known fact that there are no official runtimes for C# in non-Windows operating systems. There is the Mono project, which aims to provide a C# compiler and run-time, but it will always lag behind official C# releases because it is not officially supported by Microsoft. Let me say that for this reason, and this reason alone, I think Java remains the dominant programming language. I'm hoping that more support is given to the Mono project by Microsoft, so that C# can be a truly cross-platform language. I should note that C# is a platform-independent language, though. It has no intrinsic features (as far as the language is concerned) to be tied to Windows (for reasons to be described below). I should also note that I am a Linux user and C# remains my favorite programming language.

Some may wonder how the Mono project can even keep up with C#, without knowing the details of how the C# compiler even works. Well that is because the C# language specification is standardized by the ECMA (ECMA-334). So what does it even mean to be "standardized" anyhow? Well it gives you an exact overview of how C# should behave and how it should look. Without this, the compiler and CLI runtime could change its behavior in the middle of running or compiling a program. With the standards (from an international organization like the ECMA), we can have full faith that the C# compiler and runtime is well-defined and runs as we expect it ought to run. Java cannot say this, so it does not have the peer review of other companies to be formalized, which is a major blow to the language (although there are other opinions on this matter).

C# is also driven by people that need the language to deliver results. I have not had this experience with Java. Java is focused on purity for the language. Language features are not added if they are not compatible with past runtimes, or if they change the feeling of the language too much. C# takes a different approach by adding new features as requested by its community and trying its best not avoid feature-creep or feature bloat. The language features that are added in C# are meant to help the programmer do his job better and faster; that is something I have not seen Java do.

Well these are some high-level ideas about C# that make it a powerful language, but we should probably examine what makes the actual language more powerful than Java: Generics without type erasure, properties, documentation, delegates, lambda expressions, inferred types, LINQ, coroutines, optional parameters, dynamic types, and covariance.

Generics without type erasure
public class ArrayTest<T> {

public <T> T[] returnArray() {
return new T[10];
}
}

The above works in C#, but not in Java. The problem is that Java replaces all generic types with the Object type once it's compiled. To learn more about type erasure, see java.sun.com/docs/books/tutorial/java/generics/erasure.html

Properties

For observers and mutators, you need getters and setters. Example:
private int z;
...
public int getZ() { return z; }
public int setZ(int n) { z = n; }
Rather, in C#:
private int z ...
public Z {
get { return z; }
set { z = value; }
}
Client code:
obj.Z //C#
obj.getZ() //Java
obj.Z = 3; //C#
obj.setZ(3); //Java
Which one expresses intent better?

Documentation

Java has Javadoc. It basically generates a web page from the comments you write in your code. It's important to note this is a separate web page. It does this through special Javadoc annotations (@author, @return, etc...). From a module designers point of view, this  means his comments define the contract for the clients. So a client could rely on something that the module designer was not intending the client to use, so when the module designer goes and changes something in the interface, then he blows the contract for the clients without realizing it. There is also the issue involved with having to go to a web page to lookup the documentation, rather than having it in code (although the Eclipse IDE is getting good at parsing Javadoc output).

C# solves this by including documentation in an XML format to be serialized for the C# IDE (Visual Studio). It is part of the language. Although it does not completely solve the issues dealing with breaking the contract, because both Javadoc and the C# compiler generate documentation from the source code, it does provide a better way for clients to read the documentation (due to IntelliSense).

I also personally like the look of C#'s documentation output (see: NDoc) along with its look in the code (XML vs Javadoc annotations).

Delegates

C# has delegates. From the MSDN website:

"A delegate is a type that references a method. Once a delegate is assigned a method, it behaves exactly like that method. The delegate method can be used like any other method, with parameters and a return value..."

In programming language terms, this allows programmers to refer to methods as first-class objects. Java does not have this feature. These delegates often appear in Java as "Runnable" objects. For example, every time you want to call something for a GUI event in Java, you need to encapsulate the functionality of it within a Runnable object. This is because Java provides no way for a programmer to refer to a method (this gets back to first-class objects). Workarounds for delegates in Java are possible, but usually require heavy plumbing.

Lambda Expressions

C# has lambda expressions. These are basically very compact anonymous delegates. Here's a definition by example:
int avgAge = peopleList.average(p => p.Age); 
IEnumerable<Person> maleTeens = peopleList.where(p =>
p.Age >= 13 && p.Age <= 19 && p.Gender == Male);
This is a pretty basic example of lambda expressions. For more information, see the MSDN article about Lambda Expressions.

Type Inference

var a = "some string";

The compiler will infer the type to be string at compile-time and a is considered to be statically typed (intellisense even will assert this; try hovering over a var to see its type). This is useful for really complicated object types if you're tired of typing out long object named with complex Generic types.

LINQ

Language INtegrated Query is a novel C# feature that allows querying over any type of data source (a database, collection of objects, an XML document, anything...).  Example (from Wikipedia):
int someValue = 5; 
var results =  from c in someCollection
               let x = someValue * 2
               where c.SomeProperty < x
               select new {c.SomeProperty, c.OtherProperty};
 
foreach (var result in results)
{
        Console.WriteLine(result);
}
This is useful for data querying (which you almost always need to do in the real world of software development).

Coroutines

Coroutines allow for code blocks to be suspended and resumed at different locations. This is offered in C#'s "yield return" keyword:

public IEnumerable<Person> getPersons() {
   foreach(var p in personList) {
    if (p.IsVisible) yield return p;
   }
} 
... 
foreach(var p in getPersons()) {
   if (Environment.StopProcessing()) return;   
   else Environment.Process(p); 
}
Note that, when run, "getPersons" will not return the entire list immediately. In fact, it stops the iteration each time it calls "yield return." So when Environment.StopProcessing() is true, the rest of the list is not returned. Another way of thinking about this is that only one item is returned at a time. This could perhaps be simulated in Java using a Stream or a custom iterator.

Optional Parameters

Optional parameters are well known in most programming languages, except Java and C# (until recently). To simulate optional parameters, the trick was to create basically an overloaded tree of methods. C# has (finally) come around to offer optional parameters, like this:

public void M(int x, int y = 4) { ... }

Client call:
M(1); --> M(1, 4);

To get more fancy (from channel 9 comment by obrienslalom):
oChart.ChartWizard( oResizeRange, Excel.XlChartType.xl3DColumn, 
   Missing.Value, Excel.XlRowCol.xlColumns, Missing.Value, 
   Missing.Value, Missing.Value, Missing.Value, Missing.Value, 
   Missing.Value, Missing.Value );
becomes:
oChart.ChartWizard( 
    Source : oResizeRange, 
    Gallery : Excel.XlChartType.xl3DColumn, 
    PlotBy : Excel.XlRowCol.xlColumns
    );
This becomes a lot more readable.

Dynamic Types

This is somewhat scary to hear about in a strongly-typed language. But this is why I love C#. The design team is willing to do things that others are afraid of trying, because they tend to get categorically rejected just because there are some times when you shouldn't use them. Everyone agrees that you should avoid using dynamic typing in favor of strong types (including the C# architect). But there are times when dynamic types are totally needed, like the HTML DOM, or web services. To get around these problems, the general approach is to cast things to an object and then re-cast them back (so it's not like you were getting any strong typing anyhow). So to make things more readable and understandable, C# has implemented the dynamic type, which allows you to make calls on the object that will be resolved at run-time rather than compile-time. Example:

dynamic f = 6;
f.ToString(); //compiles, runs
f.asd(); //compiles, runtime error

Covariance

Covariance (and contravariance) is a programming language concept for type systems. To avoid going into too much detail about this, see this example:

class Animal { }
class Dog : Animal { }

IEnumerable<Dog> dogs = ...
IEnumerable<Animal> animals = dogs; //not allowed in Java

For more information about covariance and contravariance in C#, see this blog post.

Summing It Up

Well, the above features cover a lot of C# functionality that isn't possible in Java. I'm probably missing some things that C# has (extension methods comes to mind), but that isn't totally my point. Most people will agree that C# is a better language than Java. It's not as widespread in deployment as it is compared to Java, though. But does that matter for a programming language? SML is not very widespread, but it is still more powerful than C# and Java.

Just because a language is in high use doesn't make it a good language. Judge languages based on how fast you can write code that actually does something, and the amount of expressive power it has. The point of programming languages is to abstract functionality so that you can write programs faster and without as many errors. It's not the language's fault if it isn't widely used. It's really *your* fault, as a programmer, for not using it! There are problems with this ideology, I understand (library support, company standards, etc..), but you should try to program in the language that you feel will allow you to do the most in the least amount of time when possible. So when deciding to use C# or Java, try using C# some time to see how much more productive you are, given these language features (and not to mention, it has great standard library support with the .NET framework).

Overall, C# as a language has a lot of great features you won't find in a lot of languages (including Java) to make your life easier. Try broadening your programming power by using a more functional (note: not in the functional programming sense, but ability to do things) programming language. But ultimately, I am a pragmatist so it comes down to did I end up writing this program faster with this language or not? I have found that with C# I tend to write code much faster because of these language features. Its only downfall is its lack of cross-platform support, but that should not stop you from using it!

Posted in   Development
2008-12-07 19:00:08 | 316 Views

Comments

Leave a Comment

You must be logged in to comment