web-dev-qa-db-fra.com

Union C ++ en C #

Je traduis une bibliothèque écrite en C++ en C #, et le mot-clé 'union' existe une fois. Dans une structure.

Quelle est la bonne façon de le traduire en C #? Et que fait-il? Cela ressemble à ceci;

struct Foo {
    float bar;

    union {
        int killroy;
        float fubar;
    } as;
}
69
Viktor Elofsson

Vous pouvez utiliser des dispositions de champ explicites pour cela:

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

Non testé. L'idée est que deux variables ont la même position dans votre structure. Vous ne pouvez bien sûr en utiliser qu'un seul.

Plus d'informations sur les syndicats dans tutoriel struct

76
Armin Ronacher

Vous ne pouvez pas vraiment décider comment gérer cela sans savoir comment il est utilisé. S'il est simplement utilisé pour économiser de l'espace, vous pouvez l'ignorer et utiliser simplement une structure.

Cependant, ce n'est généralement pas la raison pour laquelle les syndicats sont utilisés. Il y a deux raisons courantes de les utiliser. L'une consiste à fournir 2 ou plusieurs façons d'accéder aux mêmes données. Par exemple, l'union d'un entier et d'un tableau de 4 octets est une (parmi plusieurs) façons de séparer les octets d'un entier 32 bits.

L'autre est lorsque les données de la structure proviennent d'une source externe telle qu'un paquet de données réseau. Habituellement, un élément de la structure entourant l'union est un ID qui vous indique quelle saveur de l'union est en vigueur.

Dans aucun de ces cas, vous ne pouvez ignorer aveuglément l'union et la convertir en une structure où les deux (ou plus) champs ne coïncident pas.

22
Steve Fallows

En C/C++, l'union est utilisée pour superposer différents membres dans le même emplacement de mémoire, donc si vous avez une union d'un int et d'un float, ils utilisent tous les deux les 4 mêmes octets de mémoire pour stocker, évidemment écrire sur l'un corrompt l'autre (puisque int et float ont une disposition de bits différente).

Dans .Net, Microsoft a opté pour le choix le plus sûr et n'a pas inclus cette fonctionnalité.

EDIT: sauf pour interop

3
Nir

Si vous utilisez union pour mapper les octets de l'un des types à l'autre, alors en C # vous pouvez utiliser BitConverter à la place.

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

ou;

int killroy = 125;
float fubar = BitConverter.ToSingle(BitConverter.GetBytes(killroy), 0);
2
Steve Lillis

Personnellement, j'ignorerais l'UNION tous ensemble et implémenter Killroy et Fubar comme des champs séparés

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

L'utilisation d'un UNION permet d'économiser 32 bits de mémoire allouée par l'int .... ne va pas faire ou casser une application de nos jours.

1
ckramer
public class Foo
{
    public float bar;
    public int killroy;

    public float fubar
    {
        get{ return (float)killroy;}
        set{ killroy = (int)value;}
    }
}
0
Yan Chen