Saturday, February 14, 2009

Generic Type Parameters AS Method Parameters

I have long had an interest in method contracts (pre- and post-conditions). I followed Spec# and I continue to follow the Pex project. I am also a big fan of doing argument verification at the highest possible level of a public API. I was working on a public API today which takes a Type object. My method looked like this:

public string GetClassName (Type type) {
    if (type == null) {
        throw new ArugmentNullException ("type");
    }

    if (!type.IsSubclassOf (typeof (UpnpObject)) &&
        type != typeof (UpnpObject)) {
        throw new ArgumentException (
            "The type does not derive from UpnpObject.",
            "type");
    }

    // do stuff with 'type'
}


It then occurred to me that I can do the same thing with a generic type parameter, but get all the checks for free!

public string GetClassName<T> () where T : UpnpObject {
    //do stuff with 'typeof (T)'
}


Tada! Using generic type parameters as method parameters is nothing new (Aaron has something like this in the Banshee service stack), but the really neat thing is that you can use the generic constraints as a kind of argument pre-condition. If you have a method which takes a Type, consider using a generic type parameter rather than a method parameter. It guarantees that 'null' cannot be passed and it allows you to specify ancestry, interfaces, ref/value types, and the presence of a default constructor.