Bug in C# compiler with generics ? (BadImageFormatException)

I m' having a problem with a quite simple program using generics inheritance. Running the program throws a BadImageFormatException (Exception from HRESULT: 0x8007000B).

The program defines a generic entity, factory, and entity reference (an ID and a pointer to an entity).
A "factory factory" is used to create the factories.
A User factory and a User entities are defined.

This is the program :

/// <summary>
/// Generic class defining an entity
/// </summary>
/// <typeparam name="E">The entity type</typeparam>
/// <typeparam name="F">The factory type used to create entities</typeparam>
public abstract class Entity<E, F>
where E : Entity<E, F>
where F : EntityFactory<E, F>, new()
{
private int m_Id;
private EntityRef<E, F> m_Reference;

public int Id
{
get { return m_Id; }
set
{
if (m_Reference != null)
m_Reference.Id = m_Id;
m_Id = value;
}
}

public EntityRef<E, F> Reference
{
get
{
if (m_Reference == null)
{
m_Reference = new EntityRef<E, F>(this as E);
}
return m_Reference;
}
}

}


/// <summary>
/// A generic entity reference
/// </summary>
/// <typeparam name="E">The entity type</typeparam>
/// <typeparam name="F">The factory type</typeparam>
public class EntityRef<E, F>
where E : Entity<E, F>
where F : EntityFactory<E, F>, new()
{
private E m_Entity;
private int m_Id;

/// <summary>
/// Create an entity reference from an entity
/// </summary>
/// <param name="entity"></param>
public EntityRef(E entity)
{
m_Entity = entity;
m_Id = entity.Id;
}

/// <summary>
/// Get the referenced entity
/// </summary>
public E Entity
{
get
{
if (m_Entity == null)
{
// Although these lines are never executed in this example,
// commenting them prevents the bug from appearing
F factory = FactoryFactory.Instance.GetFactory<F>();
m_Entity = factory.GetEntity((int)m_Id) as E;
}
return m_Entity;
}
}

public int Id
{
get { return m_Id; }
internal set { m_Id = value; }
}

}



/// <summary>
/// Generic factory
/// </summary>
/// <typeparam name="E">The entities to create</typeparam>
/// <typeparam name="F">The factory type</typeparam>
public abstract class EntityFactory<E, F>
where E : Entity<E, F>
where F : EntityFactory<E, F>, new()
{
public abstract E GetEntity(int id);
public abstract List<EntityRef<E, F>> GetEntitySons(EntityRef<E, F> entity);
}

/// <summary>
/// The factory factory
/// </summary>
public class FactoryFactory
{
private static FactoryFactory m_Instance = new FactoryFactory();

public static FactoryFactory Instance
{
get { return m_Instance; }
}

public F GetFactory<F>() where F: class, new()
{
return new F();
}
}



/// <summary>
/// The user class
/// </summary>
public class User: Entity<User, UserFactory>
{

}


/// <summary>
/// The user factory
/// </summary>
public class UserFactory: EntityFactory<User, UserFactory>
{
public override List<EntityRef<User,UserFactory>> GetEntitySons(EntityRef<User,UserFactory> entity)
{
return new List<EntityRef<User, UserFactory>>();
}

public override User GetEntity(int id)
{
return new User();
}
}




To have the bug appear, just run :
User u = new User(); // Create a user
u.Id = 0; // Set its Id
User u2 = u.Reference.Entity; // u.Reference seems to work, while
// U.Reference.Entity throws
// BadImageFormatException.



Is this a compiler error, or did I do something wrong.
Do you have an idea to fix this, or an elegant workaround

--
Clement


Answer this question

Bug in C# compiler with generics ? (BadImageFormatException)

  • limonada

    Since this lab is not available, any idea on when this is going to be corrected. I have run into it a couple of times and have some workarounds. In general, when this problem comes up, I resort to reflection. If I have a method that causes the BadImageFormatException, I replace any calls in it to other generics with a reflective call and this seems to work just fine, just not pretty...
  • Ganesh Sankara

    Further notes:

    It looks like it's already been reported (and fixed, but not in OUR version of the compiler!):

    http://lab.msdn.microsoft.com/productfeedback/viewfeedback.aspx feedbackid=4e95977c-560b-4d40-b3b7-2157133be7bb

    And there's a workaround for VB here, which involves a cast and which I think is the same as the workaround you found for C#:

    http://forums.microsoft.com/MSDN/ShowPost.aspx PostID=125454&SiteID=1


  • Kevin Gilpin

    Although the symptoms of the VB bug and mine are the same (BadImageFormatException), I am not sure the root cause is the same too (the compiler is different, and the source code is not that similar).

    I sumitted a bug in MSDN Product Feedback :
    http://lab.msdn.microsoft.com/ProductFeedback/viewfeedback.aspx feedbackid=9c2c6d79-505a-4672-8f1a-88ca29fb7f19

    --
    Clement Gatin

  • PaulRichardson

    People generally don't like analyzing big pieces of code and be expected to give you the correct answer. Can you reduce this down to the smallest possible If you still think you have a bug, you can report it on the Product Feedback website.
  • Bayan El Ameen

    It sure looks like a compiler bug to me! You should never be able to get a BadImageFormatException from a program.

    I'd report it as a bug here, posting that short code sample:

    http://lab.msdn.microsoft.com/productfeedback/default.aspx


  • Alexander Ivanov

    I also rely on reflection-based workarounds for that bug. And I totally agree, this just breaks any attempt to make a nice generics-based architecture or design. It seems Microsoft didn't want us to use generics for anything else than just strongly-typed lists. Althgough generics are not as powerful as C++ templates (it is even so far away from templates), I think they could allow us to make some nice design and strongly typed architectures. If there was not that bug.

    Microsoft said it was fixed and would be available for a future release. But I just can't say when this release will be available. Will we have to wait for the .NET Framework 2.1

  • mblatch

    It appears the bug was already submitted to Microsoft and will be fixed for a future version.

    See http://lab.msdn.microsoft.com/ProductFeedback/ViewFeedback.aspx FeedbackID=eb24881a-87b3-41f3-942c-1c9c944ec03e for details.

  • Jean Philippe Boucher

    I tried to make it (much) smaller :

    public abstract class AbstractClass1<E>
    where E : AbstractClass1<E>, new()
    {
    }

    public class Class1 : AbstractClass1<Class1>
    {
    }

    public class Class2<E>
    where E : AbstractClass1<E>, new()
    {
    public E GetClass1()
    {
    return Factory.GetClass<E>();
    }
    }

    public class Factory
    {
    public static E GetClass<E>() where E: class, new()
    {
    return new E();
    }
    }

    class Program
    {
    static void Main(string[] args)
    {
    Class2<Class1> c2 = new Class2<Class1>();
    c2.GetClass1();
    }
    }



    As with the previous example, I get a BadImageFormatException when the code reaches c2.GetClass1(). Is this expected A workaround is to transform GetClass<E> into GetClass(Type) in the Factory class, but I am still puzzled by the error, and I would like to know if I did something wrong, or if this is a compiler error.

    --
    Clement Gatin



  • Bug in C# compiler with generics ? (BadImageFormatException)