我在使用structlayouts搞乱了,我发现了一些我觉得很奇怪的事情:
以下代码正如我所想的那样工作:
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;
}
}
但是,如果将classB.Value更改为int,则此代码将抛出提到的FatalExecutionEngineError。
任何人都可以解释为什么或者如何解决问题?我知道这可能太复杂了,我只是在这里搞乱,但有人可能想要一些挑战。
答案 0 :(得分:0)
基本上,你所做的是完全未定义的。你是以两种非常讨厌的方式欺骗它:
object
加载dynamic
引用(object
只是int
带有一些花哨的编译器技巧)(注意;在所有情况下,这都会很可能指向垃圾;在x64的情况下,它甚至不是整个宽度,因此它将把垃圾读入取消引用的值基本上:不要那样做。这就是为什么显式布局被视为无法验证的代码。至于如何“正确”(并且我慷慨地使用该术语):
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; } }
}
如果您希望val as Foo
看到另一种类型,也可以使用(Foo)val
代替null
。