在C#中使用字符串错误对齐的联合

时间:2014-02-10 23:05:05

标签: c# union layoutkind.explicit

我使用以下代码“非对象字段错误对齐或重叠错误

public struct TypeA
{
   public string A1;
   public string A2;
}
public struct TypeB
{
   public string B1,
   public string B2;
}

我使用 System.Runtime.InteropServices LayoutKind.Explicit

一起实施 union
[StructLayout(LayoutKind.Explicit)]
public struct TypeAorB
{
   [FieldOffset(0)]
   public TypeA aa;

   [FieldOffset(0)]
   public TypeB bb;
}

我认为问题来自 struct 中的 string 。我该如何克服这个问题?

2 个答案:

答案 0 :(得分:2)

你要做的不合法。 String是引用类型,不能与union中的任何其他内容重叠。它对垃圾收集器来说很重要,它无法可靠地找出存储在字段中的引用,因此如果字符串对象需要保持活动状态,它就无法可靠地判断出来。

关于结构的奇怪之处在于,您将字符串与字符串重叠。哪个在技术上有效,没有理由让垃圾收集器混淆,因为它总是看到有效的对象引用。但它实际上并没有处理这种特殊情况,微软没有编写足够的代码,也没有关心烧掉cpu周期,以检查类型标识。

这是有充分理由的,因为不必在你的声明中重叠它们。当你可以轻易地避免重叠时,微软没有必要编写特殊代码来识别重叠。

在你的例子中,乌龟一直是下来的,联盟的每个字段是相同的。所以使用联合没有任何意义。

所以不要。

答案 1 :(得分:0)

为什么fieldoffsets一样?它们应该是0和0+ [TypeA的大小]。

类型A是8个字节,因为你有2个字符串,每个字符串将使用4个字节的指针。

...因此

    [StructLayout(LayoutKind.Explicit)]
    public struct TypeAorB
    {
        [FieldOffset(0)]
        public TypeA aa;

        [FieldOffset(8)]
        public TypeB bb;
    }

如果您要再次添加typeB的第三个字段,则需要执行以下操作:

    [StructLayout(LayoutKind.Explicit)]
    public struct TypeAorB
    {
        [FieldOffset(0)]
        public TypeA aa;

        [FieldOffset(8)]
        public TypeB bb;

        [FieldOffset(16)]
        public TypeB bb;
    }