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

Bug in C# compiler with generics ? (BadImageFormatException)
limonada
Ganesh Sankara
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
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
Bayan El Ameen
I'd report it as a bug here, posting that short code sample:
http://lab.msdn.microsoft.com/productfeedback/default.aspx
Alexander Ivanov
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
See http://lab.msdn.microsoft.com/ProductFeedback/ViewFeedback.aspx FeedbackID=eb24881a-87b3-41f3-942c-1c9c944ec03e for details.
Jean Philippe Boucher
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