Cook Computing

.NET Generics

January 1, 2005 Written by Charles Cook

Brad Wilson's post The Love Affair is Over prompted me to investigate .NET generics (long overdue I know). The gist of Brad's complaint seems to be that the following does not compile


class TestClass<T> 
{
    public void Foo(T t)
    {
        t.Bar();
    }
}

This is because the compiler cannot determine that type T will contain a method called Bar with the required signature. The C# designers decided that the compiler should not make an inference about the "latent type" of Type T. All the compiler knows from this code is that type T is of type Object.and so, for example, this compiles successfully:


class TestClass<T> 
{
    public void Foo(T t)
    {
        t.ToString();
    }
}

To compile the first class definition above it is necessary to provide a constraint on Type T, for example:


interface IBar
{
    void Bar();
}

class TestClass<T> where T : IBar
{
    public void Foo(T t)
    {
        t.Bar();
    }
}

A while ago Ian Griffiths wrote an interesting post on this topic: Generics, Latent Types, and Type Safety in which he illustrates that IL code using the concept of "latent typing" can be compiled, though it fails at runtime, which suggests that at some point in the future we might be able to write code along the lines of this:


class TestClass<T> where T : any
{
    public void Foo(T t)
    {
        t.Bar();
    }
}

Ian does however point out that the current implementation of generics prevents problems with versioning which could only be detected at runtime.

So the purpose of .NET generics in its current implementation is to make it possible to implement type-safe containers, for example, collections, and to avoid the need for downcasting in certain situations. For example, when using the XmlRpcProxyGen class in XML-RPC.NET to create a proxy, a cast is required, for example:


IFoo fooProxy = (IFoo)XmlRpcProxyGen.Create(typeof(IFoo));

With generics it will be possible to remove the need for the cast:


IFoo fooProxy = XmlRpcProxyGen.Create<IFoo>();

For a comprehensive description of how to use generics I recommend Juval Lowy's An Introduction to C# Generics.