C#StructLayout.Explicit问题

Tay*_*ese 10 .net c# clr structlayout

我试图理解为什么下面的第二个例子没有问题,但第一个例子给了我下面的例外.在我看来,两个例子都应该基于描述给出例外.任何人都可以开导我吗?

未处理的异常:System.TypeLoadException:无法从程序集'StructTest,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null'加载类型'StructTest.OuterType',因为它包含偏移0处的对象字段,该字段未正确对齐或重叠由非对象字段.
在StructTest.Program.Main(String [] args)按任意键继续...

例1

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;

namespace StructTest
{
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    struct InnerType
    {
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 100)]
        char[] buffer;
    }

    [StructLayout(LayoutKind.Explicit)]
    struct OuterType
    {
        [FieldOffset(0)]
        int someValue;

        [FieldOffset(0)]
        InnerType someOtherValue;
    }

    class Program
    {
        static void Main(string[] args)
        {
            OuterType t = new OuterType();
            System.Console.WriteLine(t);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

例2

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;

namespace StructTest
{
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    struct InnerType
    {
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 100)]
        char[] buffer;
    }

    [StructLayout(LayoutKind.Explicit)]
    struct OuterType
    {
        [FieldOffset(4)]
        private int someValue;

        [FieldOffset(0)]
        InnerType someOtherValue;

    }

    class Program
    {
        static void Main(string[] args)
        {
            OuterType t = new OuterType();
            System.Console.WriteLine(t);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Meh*_*ari 12

公共语言运行库包含一个验证程序,用于确保正在运行的代码(可验证的IL)不可能破坏托管环境中的内存.这可以防止您声明字段重叠的结构.基本上,您的struct包含两个数据成员.一个整数(4个字节)和本机整数(指针大小).在32位CLR上,你可能正在运行你的代码,这char[]将占用4个字节,所以如果你把整数小于4字节远离结构的开头,你将有重叠的字段.有趣的是,由于指针大小为8字节,因此两个代码片段在64位运行时都失败.

  • 规则更加晦涩难懂。引用类型的两个字段(甚至完全不相关)_can_ 重叠,在这种情况下,程序集有效,但不可验证(因此它将在 FullTrust 中运行)。所以你仍然可以通过重叠对不兼容类型的引用来把事情搞砸。我认为“部分重叠”限制的原因是因为绝对保证将GC吹出水面。而在完全引用重叠的情况下,GC 会做得很好,而且当您有一个鉴别器字段来跟踪类型时,它实际上很有用(以节省强制转换运行时类型检查)。 (2认同)