Generic Methods as Casts

Somebody just asked me which of the following API design alternatives is better. They both do what we could call “casting.”

 

// Generic Method “Cast”

var foo = someInstance.SomeMethod<IFoo>();

 

// Simple Cast

var foo = (IFoo)someInstance.SomeMethod();

The Generic method approach can potentially have two benefits. A constraint can tell users what the subset of valid casts is. For example, the following API will allow casts to a collection (a subtype of IEnumerable):

 

public TCollection SomeMethod<TCollection>() where TCollection:IEnumerable {

    …

}

If the user calls this method and tries to “cast” the return value to let’s say an Int32, the compiler with complain. For example,

 

var int someInstance.SomeMethod<int>();

… will generate the following error:

 

The type 'int' must be convertible to 'System.Collections.IEnumerable' in order to use it as parameter 'TCollection' in the generic type or method 'SomeClass.SomeMethod<TCollection>()'

Secondly, the Generic method might do different things based on the type parameter. The method relying on a simple cast has now knowledge about the type the user will cast it’s return value to.

 

public TCollection SomeMethod< TCollection >()

    where TCollection:IEnumerable,new() {

   

    TCollection newCollection = new TCollection ();

    ArrayList newArray = newCollection as ArrayList;

    if (newArray != null) newArray.Capacity = 0;

    return newCollection;

}

If neither of these benefits applies in your case, I would use a simple cast. It’s more transparent in terms of what’s going on. The users of a generic method might wonder what kind of “magic” is being done with the generic type parameter.