Wednesday, March 26, 2008

I like generics.

I even like C# generics.

In general C# generics are better than Java Generics.

The problem is C# generics are not the generics per se, it's all the crap to integrate generics in the language that suck.

Firstly let me clarify why C# generics are better:
  • The are reified, in other words M$ broke backward compatibility and integrated generics into the core runtime so Foo<string> and Foo<int> are two different types as far as the .Net runtime (or at least compiler) is concerned.

  • No wildcards, none of the "?" and "extends MyType" crap you have in Java.


  • That's where the good stuff ends onto the sucky bits...

    C# has two methods of casting: An exception safe cast and non-exception safe cast.

    The non exception safe cast looks pretty much like the standard Java cast:

    Object o = new String("hello");
    String s = (String) o;

    The major difference is that in C# if o is null, this cast will blow up. So the C# team added a safe cast which looks like so:

    Object o = new String("hello");
    String s = o as String;

    If either o is not of type String or is null, s will in turn be set to null, so in order to make this code safe you have to do as follows:

    Object o = new String("hello");
    String s = o as String;
    if (s != null)
    {
    //do stuff here
    }

    There are some obvious problems with this approach:
  • Bad code won't fail fast, we are back to the old "check if method returned 0" paradigm.

  • There is no way to determine what went wrong here, is o null or is it the wrong type, this could manifest in tons of subtle bugs with people passing in the wrong types.


  • "Ok so what has this got to do with generics?" you ask

    Remember I said that .Net generics are reified. Well, it turns out that when you type something in .Net you REALLY, REALLY type it

    Take this example:

    class Foo<T,S> where T : AClass
    where S : BClass<T>
    {
    }

    this will not work:

    Foo<T,S> var = anObject as Foo<T, BClass<T>>

    you have to use:

    Foo<T,S> var = anObject as Foo<T, S>;

    since the runtime system will interpret this as two different types.

    Now this is great, but now as you will recall I indicated that the "as" style cast won't blow up and just return null if the cast fails.

    So instead of blowing up the system happily executed code that was broken and gave me a NullReferenceException (.Net equivalent of NullPointerException),way, way, way down in the code.

    No comments: