blogs.conchango.com

welcome to the conchango blogging site
Welcome to blogs.conchango.com Sign in | Join | Help
in Search

Paulo Reichert's Blog

Generics compilation bug in .NET 2.0

Well, it seems that this week I have been hitting every bug and/or unexpected behavior in the .NET Framework 2 & 3. What is more frustrating is that none of these bugs will be fixed imdiately, some being scheduled for "Orcas" and some for even later releases of the Framework.

 The most importants of these bugs are one on WCF reliable messaging and another one when compiling generics code. The first I will leave for another post and will concentrate on the second bug here.

 I have written a piece of code similar (conceptually) to the following:

namespace CoreLibrary

{

    public class BaseClass<T> where T : class, new()

    {

        public virtual string DoSomething()

        {

            T obj = new T();

            return string.Format("The type used is {0}.", obj.GetType().FullName);

        }

    }

 

    public class ChildClass<T, Y> : BaseClass<T>

        where T : SideClass<Y>, new()

        where Y : class, new()

    {

        public override string DoSomething()

        {

            T objT = new T();

            Y objY = new Y();

 

            return string.Format("The two types used for this class are {0} and {1}.", objT.GetType().FullName, objY.GetType().FullName);

        }

    }

 

    public class SideClass<T>

    {

        public string DoSomethingElse()

        {

            return "Did something else!";

        }

    }

}

And the program to run that looks like:

namespace Program

{

    class Program

    {

        static void Main(string[] args)

        {

            ChildClass<SideClass<object>, object> obj = new ChildClass<SideClass<object>, object>();

            Console.WriteLine(obj.DoSomething());

            Console.Read();

        }

    }

}

When I run the above code I get a System.BadImageFormatException.

It works out to be a bug in the compiler itself as reported here. To solve this, I had to change the BaseClass<T> to the following:

public class BaseClass<T> where T : new()

{

    public virtual string DoSomething()

    {

        T obj = new T();

        return string.Format("The type used is {0}.", obj.GetType().FullName);

    }

}

By removing the class constraint from T in the base class, everything compiles and works fine. In the actual code I was using in my project, T was constrained to reference types so that I could use some better casting and stuff like that, but in reality I could do just fine without constraining so that wasn’t an issue after all.

The bug in WCF is a bit more complex and I will post more about that later on as soon as I get time to write the article.

Published 22 February 2007 12:44 by paulo.reichert
Filed under:

Comments

 

john.rayner said:

A very minor point about the code (which is completely unrelated to your post), but instead of:

T obj = new T();

return string.Format("The type used is {0}.", obj.GetType().FullName);

you can use:

return string.Format("The type used is {0}.", typeof(T).FullName);

This would put less pressure on the garbage collector and (in the example above) would mean that you don't need the constructor constraint on T.

February 23, 2007 10:46
 

paulo.reichert said:

Thanks John,

I indeed wouldn't instantiate the object just to get its type in a real life app. The instantiation there was more to force it to run the constructor (and make sure it has ran any initialization code) and the console line afterwards I have put there just to allow me to verify it had created the correct type.

In the real code I have implemented on my app I have added the class and new() constraints for other reasons, but as I needed to duplicate the weird behaviour I was getting there in this sample code I wrote some simple code that isn't necessarily best practice.

February 26, 2007 16:14
Anonymous comments are disabled
Powered by Community Server (Personal Edition), by Telligent Systems