82

我正在将一个用 C++ 编写的库翻译成 C#,并且关键字“union”存在一次。在一个结构中。

将它翻译成 C# 的正确方法是什么?它有什么作用?它看起来像这样;

struct Foo {
    float bar;

    union {
        int killroy;
        float fubar;
    } as;
}
4

6 回答 6

89

您可以为此使用显式字段布局:

[StructLayout(LayoutKind.Explicit)] 
public struct SampleUnion
{
    [FieldOffset(0)] public float bar;
    [FieldOffset(4)] public int killroy;
    [FieldOffset(4)] public float fubar;
}

未经测试。这个想法是两个变量在你的结构中具有相同的位置。当然,您只能使用其中之一。

结构教程中有关联合的更多信息

于 2008-09-24T12:24:41.107 回答
22

如果不了解它的使用方式,您将无法真正决定如何处理它。如果它只是用来节省空间,那么你可以忽略它而只使用一个结构。

然而,这通常不是使用联合的原因。使用它们有两个常见的原因。一种是提供两种或多种方式来访问相同的数据。例如,int 和 4 字节数组的联合是分离 32 位整数字节的一种(多种)方法。

另一种是结构中的数据来自外部源,例如网络数据包。通常,包含联合的结构的一个元素是一个 ID,它告诉您联合的哪种风格有效。

在这两种情况下,您都不能盲目地忽略联合并将其转换为两个(或更多)字段不重合的结构。

于 2008-09-24T15:37:33.013 回答
4

在 C/C++ 中,联合用于覆盖同一内存位置中的不同成员,所以如果你有一个 int 和一个 float 的联合,它们都使用相同的 4 字节内存来存储,显然写入一个会破坏另一个(因为int 和 float 有不同的位布局)。

在 .Net 中,Microsoft 选择了更安全的选择,并且没有包含此功能。

编辑:除了互操作

于 2008-09-24T12:25:03.337 回答
4

如果您使用 将union其中一种类型的字节映射到另一种类型,则可以在 C# 中使用BitConverter

float fubar = 125f; 
int killroy = BitConverter.ToInt32(BitConverter.GetBytes(fubar), 0);

或者;

int killroy = 125;
float fubar = BitConverter.ToSingle(BitConverter.GetBytes(killroy), 0);
于 2016-09-21T10:47:51.417 回答
0

就个人而言,我会一起忽略 UNION 并将 Killroy 和 Fubar 实现为单独的字段

public struct Foo
{
    float bar;
    int Kilroy;
    float Fubar;
}

使用 UNION 可以节省 32 位由 int 分配的内存......这些天不会制造或破坏应用程序。

于 2008-09-24T12:34:54.920 回答
-4
public class Foo
{
    public float bar;
    public int killroy;

    public float fubar
    {
        get{ return (float)killroy;}
        set{ killroy = (int)value;}
    }
}
于 2018-06-29T08:49:51.633 回答