Im messing arround with structlayouts and I found some thing i find quite odd:
The following code is working as i thought it would:
using System;
using System.Runtime.InteropServices;
public class Program
{
[STAThread]
static void Main()
{
Magic m = new Magic
{
InstanceA = new ClassA(),
InstanceB = new ClassB {Value="47"}
};
Console.WriteLine(m.InstanceA.Value);
Console.ReadKey();
}
class ClassA
{
public dynamic Value;
}
class ClassB
{
public string Value; // Change to int and it will get messy
}
[StructLayout(LayoutKind.Explicit)]
struct Magic
{
[FieldOffset(0)]
public ClassA InstanceA;
[FieldOffset(0)]
public ClassB InstanceB;
}
}
However, if you change classB.Value to int, this code will throw the mentioned FatalExecutionEngineError.
Can anyone explain why or maybe how to workarround? I know this is probably way too complicated and im just messing arround here but someone might want some challenge.
Basically, what you have done is completely undefined. You are tricking it in two very nasty ways:
object
reference (dynamic
is just object
with some fancy compiler tricks) from an int
(note; in all cases this will most likely point to garbage; in the case of x64, it isn't even an entire width, so it will be reading garbage into the value to dereferenceBasically: don't do that. This is incidentally why explicit layout is treated as unverifiable code. As for how to do it "properly" (and I use that term generously):
class Magic
{
private object val;
public ClassA InstanceA { get { return (InstanceA)val;} set { val = value; } }
public ClassB InstanceB { get { return (InstanceB)val;} set { val = value; } }
}
You could also use val as Foo
instead of the (Foo)val
if you want to see null
when it is the other type.