While I was trying to solve a problem with the author of
Rail, it seems that we have discovered a not so little bug inside the .net framework.
I explain. All of this concerns the UnderlyingSystemType of a Type. In .net you may manipulate types like :
- Arrays
- References
- Enumerations
typeof(AType[]) is very different from typeof(AType). You may want to know what is the "underlying type" from an array.
For example :
Console.WriteLine(typeof(AType[]).UnderlyingSystemType.ToString());
Console.WriteLine(typeof(AnEnum).UnderlyingSystemType.ToString());
Should write :
AType
System.Int32
Instead of this expected behavior, the result is :
AType[]
AnEnum
So the UnderlyingSystemType property of a Type does not reflect the real "underlying system type".
This is a real problem when playing with System.Reflection.Emit. For example, you define a new assembly, a new module, and then, a new type.
On this type you want to add a field, and you want it to be of type AnEnum. This seems simple, you can write it like that :
FieldBuilder myFieldBuilder= myTypeBuilder.DefineField("MyField",
typeof(AnEnum),FieldAttributes.Public|FieldAttributes.Static);
Ok, now let set it a value :
myFieldBuilder.SetConstant(SomeHelper.GetExpectedConstant());
The helper may for example get the value on a field using System.Reflection (that what we were doing), so it returns an Object.
But we can use System.Reflection to see that the expected value of the field is an integer. It is not amazing, in the assembly, the value of an enum is storred as an int32 if the underlying system type of the enum is int32. So we set the constant, everything compiles, we run it, and here, we caught an ArgumentException saying that the type of the constant does not match the type of the field...
After a short look inside the code of the BCL using the
SSCLI, we can see that if the type of the wanted field is an enum, it will check if the underlying system type of the enum matches the type of the constant. It's normal behavior, but remember, the underlying system type is not the expected one. So it is blocking, and also frustrating.
I've mailed some guys I know inside Microsoft, and I'm waiting for their answers...
But you know what is good ?
...
It works with Mono 1.0 :)
Mono set the underlying system type to the correct one, that allows my snippet to run
The problem seems to be still there in the Framework 2 beta 1.
If someone knows who I may contact, or tells me that I'm wrong, I'll be glad to discuss with him :)
This sounds amazing that no one noticed that before. So I wonder about my understanding of the thing...
And of course the sscli runs into the same behaviour as the .net 1.1 framework.
UPDATE : I've removed the code samples because I think they were not relevant enough. I will try to make one soon.