我正在将一份用C ++编写的库翻译成C#,其中关键字“union”出现了一次。在一个结构体中。
将其正确地翻译成C#的方式是什么?它是做什么的?看起来像这样;
struct Foo {
float bar;
union {
int killroy;
float fubar;
} as;
}
我正在将一份用C ++编写的库翻译成C#,其中关键字“union”出现了一次。在一个结构体中。
将其正确地翻译成C#的方式是什么?它是做什么的?看起来像这样;
struct Foo {
float bar;
union {
int killroy;
float fubar;
} as;
}
您可以使用显式字段布局来实现:
[StructLayout(LayoutKind.Explicit)]
public struct SampleUnion
{
[FieldOffset(0)] public float bar;
[FieldOffset(4)] public int killroy;
[FieldOffset(4)] public float fubar;
}
未经测试。这个想法是你的结构体中有两个变量处于相同的位置。当然,你只能使用其中一个。
有关联合体的更多信息,请参阅结构体教程
如果不知道联合体是如何使用的,就很难决定如何处理它。如果只是用于节省空间,那么可以忽略它,直接使用结构体。
然而,这通常不是使用联合体的原因。一个常见的原因是提供两种或更多访问相同数据的方式。例如,整数和4个字节的数组的联合体是将32位整数的字节分离出来的一种(众多)方式之一。
另一个原因是当结构体中的数据来自外部源,例如网络数据包时。通常,封装联合体的结构体中的一个元素是告诉您哪个联合体是有效的 ID。
在这两种情况下,都不能盲目地忽略联合体并将其转换为两个(或更多)字段不重合的结构体。
在C/C++中,联合体用于在同一内存位置上叠加不同的成员。因此,如果您有一个包含int和float的联合体,则它们都使用相同的4个字节的内存来存储,显然写入其中一个会破坏另一个(因为int和float具有不同的位布局)。
在.Net中,Microsoft选择了更安全的选项,并未包括此功能。
编辑:除了互操作性。
如果您正在使用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);
public class MyUnion
{
private object _id;
public T GetValue<T>() => (T)_id;
public void SetValue<T>(T value) => _id = value;
}
个人而言,我会完全忽略 UNION 并将 Killroy 和 Fubar 实现为单独的字段
public struct Foo
{
float bar;
int Kilroy;
float Fubar;
}
使用 UNION 可以节省 int 分配的 32 位内存...这在现今的应用程序中并不会成为决定性因素。
public class Foo
{
public float bar;
public int killroy;
public float fubar
{
get{ return (float)killroy;}
set{ killroy = (int)value;}
}
}