Advertisements
Posted by: jsonmez | February 2, 2010

C# vs Java Part 1: The Languages (Continued)

Continued from C# vs Java Part 1: The Languages

Primitive Types and Boxing

There are a few subtle differences here that can really throw a programmer off.  I think the best way to describe this section is by examples.

In C# this is valid


56.ToString();

In Java it looks like this


((Integer)56).toString();

Because both languages can autobox, I expect that I can use a primitive type like an object.  The C# syntax seems more natural to me.  I don’t want to have to think about Integer vs int.  Although a programmer should be aware about boxing, for the most part it should seem transparent.  Although, sometimes it is too transparent.  Take a look at this innocent looking Java code.

if(myObject.isFantastic())
{
   // do something
}

If this code throws a null pointer exception, what can you assume?  Ok, now what if I told you myObject is not null?  Confused a bit?  Here is the strange part.  If isFantastic returns a Boolean instead of a boolean it will be automatically unboxed into a boolean.  If isFantastic returns a Boolean with a value of null, and it tries to unbox it, the result will be a null pointer exception.  The compiler is automatically doing this for you.

if((boolean)myObject.isFantastic())
{
   // do something
}

This happens to be the syntax that you must use for C#.  Is this a bad thing or a good thing?  There are arguments either way, but if you have been bit by this automatic unboxing null pointer, you would probably say it was bad.

One final word on primitives.  C# language allows a nullable primitive type by using a ? before the variable declaration.  So, you can declare a primitive type which is null by typing int? myNullableInt. Whether this is good or bad, I am not completely sold on.  It is very useful when you use it properly to eliminate repetitive code, but in general nulls are bad.  Nulls creates extra complexity, and should be avoided if at all possible.

Generics

The handling of generics between C# and Java is pretty transparent at a surface level.  I would say that when I am writing Java code vs C#, I don’t really think about the differences in generics.

Basically Java uses type erasure, and C# includes generics support in the IL code that is generated.   Translation: Java compiler erases your generic types and replaces them with casts.  C# includes in the generic types in the byte code that runs inside the Common Language Runtime (CLR).

The easiest way to demonstrate the differences is with these code snippets, which I stole from a very informative post on generics in C# and Java.

static  void genericMethod (T t) {
T newInstance = new T (); // error: type creation
T[] array = new T [0];    // error: array creation

Class c = T.class;        // error: Class querying

List<T> list = new ArrayList<T> ();
if (list instanceof List) {}
// error: illegal generic type for instanceof
}

Contrast this to C# generics implementation which allows these things

static void GenericMethod<T> (T t)
where T : new() {
T newInstance = new T (); // OK - new() constraint.
T[] array = new T [0];    // OK

Type type = typeof(T);    // OK

List<T> list = new List<T> ();
if (list is List<String>) {} // OK
}

A few times working in Java I have wanted to know type of the generic parameter, but in general I haven’t seen the type erasure of Java pose much of a problem.  So why did Java chose to implement generics as erasures?  To maintain backwards compatibility with the JVM.  By not changing the structure of the .class files compatibility is maintained.

Exceptions

There is only one major difference in exception handling between C# and Java.  Java contains the notion of checked exceptions, which are basically exceptions that must be handled by the caller of that code.  In Java you can declare “throws ExceptionType” in the method declaration, and any callers of that method must somehow handle that exception.  This seemed like a good idea, but in general really tends to be an annoyance more than anything.  I have seen a large amount of Java code where the programmer simply declares any empty catch block and “eats” the exception, in order to make the code compile, because he/she is required to catch a checked exception.  Checked exceptions also tend to break encapsulation as changes to internal implementations are propagated upwards and can break the caller.

There is also a small difference in finally blocks.  In Java a finally block can contain a return or break statement, in C# it cannot.  The net effect of this is that you can have some strange Java code that returns in the method and in the finally block.  C# also does not process the finally block code when an uncaught exception is thrown, (looks like I was wrong here.  The CLI standard seems to be conflicting on this issue.  In 12.4.2.5 Overview of exception handling, it indicates that when there is an uncaught exception the finally block is not called.  When I tested this out with real code, the finally block was indeed called), while Java will process the finally block.  To make up for this C# uses the IDisposable interface with a using statement to allow for clean up when objects go out of scope.

Syntactic Sugar and Other Niceties

This is the part from a language perspective where Java really takes a pounding.  C# has been implementing many language level features that make writing C# code very easy and nice.

LINQ – this features allows writing code that looks more like a SQL query.  This is best demonstrated with an example.

string[] names = { "Burke", "Connor", "Frank",
                       "Everett", "Albert", "George",
                       "Harris", "David" };

IEnumerable<string> query = from s in names
                               where s.Length == 5
                               orderby s
                               select s.ToUpper();

foreach (string item in query)
     Console.WriteLine(item);

This “magic” is actually equivalent to:

IEnumerable<string> query = names
                            .Where(s => s.Length == 5)
                            .OrderBy(s => s)
                            .Select(s => s.ToUpper());

The best thing about LINQ is it allows full intellisense support, so when you type “s.” it auto-suggests all the methods available on a String.

Extension Methods – basically this allows of the creation of static methods that look like they are part of the class they extend.  LINQ uses this feature to create the simple syntax and allow any type that implements IEnumerable to gain all the abilities that are provided in the LINQ namespace like the Where or OrderBy method.

Properties – C# allows a programmer to not have to create getter and setter methods.  In addition, properties can be specified without even declaring the private member variable in the class.  A default is created and can still be later replaced with a user defined implementation so it does not violate encapsulation.

Operator Overloading – Specifically indexers.  It is nice to have a dictionary that you can put things in with dictionary[“name”] = value as opposed to dictionary.put(“name”) = value.

Anonymous Types and Var – C# will allow a code to create a new type inline with properties automatically created.  This is very useful for reducing large amounts of code where needed.  Here is an example:

var productQuery =
    from prod in products
    select new { prod.Color, prod.Price };

foreach (var v in productQuery)
{
    Console.WriteLine("Color={0}, Price={1}", v.Color, v.Price);
}

You can see how with anonymous types and the var keyword, (which is still statically typed, but allows for the compiler to specify the type instead of the programmer), we can create a type which we only need for a brief period of time.

?? – the null-coalescing operator in C# is useful for trimming down code that would normally have an if null do this/else copy value.

As I said at the beginning of this section,  C# kind of pounds Java into the ground here as far as language features that are really just ease-of-use or syntactic sugar.  Java does have one syntactic sugar feature I can think of.

Static imports – With Java you can declare

import static java.lang.Math.PI;

This import statement will allow the use of the constant PI anywhere in the class file as if it were locally declared.

Conclusion

From a language standpoint I have to admit that I do clearly prefer C# over Java.  I think it is very hard to objectively compare Java and C# and pick Java purely from a language perspective.  In the other parts of my series I will cover other areas where Java has more advantages.  I’m not against Java, I use it almost everyday, but from a perspective of language design, it has been left behind in the dust.  Microsoft seemed to make the C# language design adopt to the ease-of-use of the programmer.  I look forward to seeing how Java advances to catch up with some of these C# features and make the language experience better.

What do you think?  Do you think I have fairly portrayed both languages from a developer perspective?

NZRCDXPKP6TJ

Advertisements

Responses

  1. […] Development from John Sonmez's Perspective « Static Methods will Shock You C# vs Java Part 1: The Languages (Continued) […]

  2. It looks like your blog hasn’t been running too long but I’m really enjoying the posts you’ve put up thus far.

    I’ve never did much with Java but I use the C# features you’ve mentioned almost daily. It’s fun to get an idea of what developing in Java might feel like.

    FYI to declare a nullable int (or any other primitive type) you put the ? *after* the type not before it.

    int? myInt = null;

    as opposed to

    ?int myInt = null;

    Keep up the great posts! Good stuff!

    • Thanks Joe, and thanks for the correction. I just fixed it now. I am glad you are enjoying the posts.

      • One more note, a nullable value type like int? you mention is shorthand (aka syntactic sugar) for the generic struct Nullable. So:

        int? i = 0;
        Nullable j = 0;

        (i.GetType() == j.GetType()) == true;

        I agree with some of the other commenters that the nullable value types are most often used in database scenarios, but sometimes the abstraction is useful to represent the lack of information even in non database contexts.

  3. I think it’s interesting that almost every C# item in the syntactic sugar section are from .NET 3.x which I think says a lot about 3.x in good ways. 1.x was an almost good-enough framework. 2.0 made it all the way to the finish line by removing the painful un/boxing that permeated 1.x, not just by adding generics but also by applying them appropriately throughout the CLR. 3.x adds all of the magic that makes data a first class citizen (including lambdas, anon expressions, extension methods, sql-like intellisense) and all of the right pain-relieving syntactic sugar. I don’t *need* to be able to write properties in 1 line and with no extra explicit private var, but it makes my code so much less stressful and more declarative when I can.

    • I agree with you 100%. It is really amazing how far .NET has come in a fairly short amount of time. As I was writing this post I was realizing all the little things I take for granted when writing C# code. There are so many nice little polishes.

  4. “So, you can declare a primitive type which is null by typing int? myNullableInt. Whether this is good or bad, I am not completely sold on. It is very useful when you use it properly to eliminate repetitive code, but in general nulls are bad. Nulls creates extra complexity, and should be avoided if at all possible.”

    I find having nullable primitives reduces a lot of complexity if you are working with databases.
    Before nullables in .Net 1 you had to do a lot of extra checking for IsDBNull() to see if an int column was null in the database. When saving back into the database you had to know if 0 meant that the user had entered 0 as the value or if it meant the user had entered no value – sometimes people would end up using -1 to mean no value which made things more complex.

    • You are correct there. That is part of the reason I am unsure about nullable primatives. It is very good in working with databases, where nulls are part of the domain. In fact that is exactly where I have used nullable types myself and found them to save huge amounts of repetitive code. The problem is that these nullable types really shouldn’t bubble up past the data access layer, and make their way into the main code base or business logic. The less we have to worry about null, the simpler our code can be.

  5. Thanks for this very nice post. This series will support some of the arguments I had with my mate. I have worked in java and enjoyed it but i was always amazed to hear my team manager advising us to use some internal API (organizational) for some of the very comon purpose and jdk had one arround to solve the problem for ages.

    I always wondered why have my organisation has done this extra work for. But to be honest, for every java based open source ApI out there, I realised it is not worth to go for one until its third release or over.

    Finally switched to C# and programming happily ever after. One language, One ID and focused.

  6. Hey,
    Stackoverflow podcast listener here. I guess it worked 🙂 some traffic to your blog.

  7. Your statement about finally blocks not running in C# is incorrect. Finally blocks run regardless of whether the try block throws an exception that is caught or uncaught.

    • You are correct. This is kind of strange though. In the CLI standard it says:

      12.4.2.5 Overview of exception handling
      See the exception handling specification in Partition II for details.
      Each method in an executable has associated with it a (possibly empty) array of exception handling
      information. Each entry in the array describes a protected block, its filter, and its handler (which shall be a
      catch handler, a filter handler, a finally handler, or a fault handler). When an exception occurs, the CLI
      searches the array for the first protected block that
      • Protects a region including the current instruction pointer and
      • Is a catch handler block and
      • Whose filter wishes to handle the exception
      If a match is not found in the current method, the calling method is searched, and so on. If no match is found
      the CLI will dump a stack trace and abort the program.

      [Note: A debugger can intervene and treat this situation like a breakpoint, before performing any stack
      unwinding, so that the stack is still available for inspection through the debugger. end note]
      If a match is found, the CLI walks the stack back to the point just located, but this time calling the finally and
      fault handlers. It then starts the corresponding exception handler. Stack frames are discarded either as this
      second walk occurs or after the handler completes, depending on information in the exception handler array
      entry associated with the handling block.

      Yet, I have created a small program that does:

      try
                  {
                      Console.Out.WriteLine("In Try");
                      throw new Exception();
                  }
                  finally
                  {
                      Console.Out.WriteLine("In Finally");
                  }
      

      Which outputs:

      In Try

      Unhandled Exception: System.Exception: …

      In Finally

      So it obviously does call the finally block. I will update the post to reflect that. Thanks for bringing that point up.

  8. Following up to my comment in your previous post, here’s the Scala code.

    56.toString

    Scala 2.8 has manifest types which allow you to reflect on the type parameter T so some of the examples you show there are possible.

    Scala doesn’t have checked exceptions.

    Scala’s for comprehensions allow you to write the kind of code that LINQ’s magic is for.

    val query = names.filter(_.length == 5).sorted.map(_.toUpperCase)

    Scala has type inference so you don’t need to specify types in many places.

    Scala has implicits that let you add methods to any class and pick the scope where those additional methods are visible. For example, Scala has a RichString class that has additional methods beyond String. It’s not like Ruby where if you extend a class the entire process sees those modifications, in Scala, the additional methods are only visible where you want them and it’s done at compile time.

    Regards,
    Blair

  9. […] C# vs Java Part 1: The Languages (Continued) […]

  10. One thing you’re missing from the Generics section which does favour Java is wildcards. Allows ArrayList to “inherit” (term used loosely) from ArrayList when Foo inherits from Bar.
    I think c# 4.0 is getting something similar.

    Also I disagree about Enums, as much as I’m not a huge fan of C# Enums (too lightweight) I think Java ones are just as annoying but in a completely different way (too heavy).

    • Hi Chris,

      You are correct about the generics. I think C# is getting support for contravariance and covariance in 4.0, which should all something that takes base type of a generic to take a subtype.

      The Java enums are a bit heavy, but it is pretty useful when you need it. I agree with you that there might be a better solution, but between the two I have to go with the Java implementation.

  11. Any language you use will have different feature even if syntax and keywords are similar which mainly has to do with libraries available and compiler whether interpreted/compiled.
    C# does have advantages but only do to the .Net library giving the language more functionality where JAVA depends on open source jars which Sun is kicking themselves in the booty due to making it open source in the first place (too late now).

  12. From a Java Developer’s propective – my hats off to everyone for being objective and very informative – I do have one question though – are there plans to port the CLR to other platforms like unix/linux?

    • CLR is currently ported. Check out the Mono project.

  13. C# to java converters are now available online where you can convert your c# code to java instantly and correctly without any error one such service is being provided by codeporting.com


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Categories

%d bloggers like this: