I'm translating a library written in C++ to C#, and the keyword 'union' exists once. In a struct.
What's the correct way of translating it into C#? And what does it do? It looks something like this;
struct Foo {
float bar;
union {
int killroy;
float fubar;
} as;
}
-
You can use explicit field layouts for that:
[StructLayout(LayoutKind.Explicit)] public struct SampleUnion { [FieldOffset(0)] public float bar; [FieldOffset(4)] public int killroy; [FieldOffset(4)] public float fubar; }
Untested. The idea is that two variables have the same position in your struct. You can of course only use one of them.
More informations about unions in struct tutorial
Khoth : Note that this will work only if the types involved are primitive types (like int and float). Once objects are involved, it won't let you.Taylor Leese : Does it work with value types (like enum) or just primitive types?From Armin Ronacher -
In C/C++ union is used to overlay different members in the same memory location, so if you have a union of an int and a flat they both use the same 4 bytes of memory, obviously writing to one corrupts the other (since int and float have different bit layout).
In .net MS went with the safer choice and didn't include this feature.
EDIT: except for interop
tloach : that could be because .NET is higher-level and you probably don't have to worry about explicitly serializing data and transferring between little-endian and big-endian machines. Unions provide a nice way to convert, using the trick a previous comment noted.From Nir -
Personally, I would ignore the UNION all together and implement Killroy and Fubar as separate fields
public struct Foo { float bar; int Kilroy; float Fubar; }
Using a UNION saves 32 bits of memory allocated by the int....not going to make or break an app these days.
KPexEA : this might not work depending on how it is accessed by other parts of the library, in some instances you can write to one instance and read from the other to get the same data but in a slightly different format, that functionality will be broken if you split it into two distinct variablesFrom ckramer -
You can't really decide how to deal with this without knowing something about how it is used. If it is merely being used to save space, then you can ignore it and just use a struct.
However that is not usually why unions are used. There two common reasons to use them. One is to provide 2 or more ways to access the same data. For instance, a union of an int and an array of 4 bytes is one (of many) ways to separate out the bytes of a 32 bit integer.
The other is when the data in the struct came from an external source such as a network data packet. Usually one element of the struct enclosing the union is an ID that tells you which flavor of the union is in effect.
In neither of these cases can you blindly ignore the union and convert it to a strucet where the two (or more) fields do not coincide.
From Steve Fallows -
It might be safer but when you're interacting with C libraries that provide these sorts of data structures this decision in C# breaks even the rudimentary encapsulation of your C/C++ structures.
I'm trying to deal with something like this:
struct LibrarySType { AnotherType *anotherTypeBuff; int oneSetOfFlags; int anotherSetOfFlags; union { struct { int structMember1; ... } oneUseOfThisLibraryType; struct { char *structMember2; ... } anotherUseOfThisLibraryType; ... } u; int64 *moreStuff; ... you get the idea
}
Now I didn't invent this clever data structure, but it's part of a vendor API I need interface with it. Having to count the field offsets for each member is ridiculous. That's why compilers were invented.
From Steve Wart
0 comments:
Post a Comment