Domanda

Sto traducendo una libreria scritta in C ++ in C # e la parola chiave "unione" esiste una volta. In una struttura.

Qual è il modo corretto di tradurlo in C #? E cosa fa Sembra qualcosa del genere;

struct Foo {
    float bar;

    union {
        int killroy;
        float fubar;
    } as;
}
È stato utile?

Soluzione

Puoi usare layout di campo espliciti per questo:

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

Non testato. L'idea è che due variabili abbiano la stessa posizione nella tua struttura. Ovviamente puoi usarne solo uno.

Ulteriori informazioni sui sindacati in tutorial di struttura

Altri suggerimenti

Non puoi davvero decidere come gestirlo senza sapere qualcosa su come viene utilizzato. Se viene semplicemente utilizzato per risparmiare spazio, è possibile ignorarlo e utilizzare solo una struttura.

Tuttavia, di solito non è questo il motivo per cui vengono utilizzati i sindacati. Ci sono due motivi comuni per usarli. Uno è fornire 2 o più modi per accedere agli stessi dati. Ad esempio, l'unione di un int e un array di 4 byte è uno (di molti) modi per separare i byte di un numero intero a 32 bit.

L'altro è quando i dati nella struttura provengono da una fonte esterna come un pacchetto di dati di rete. Di solito un elemento della struttura che racchiude l'unione è un ID che ti dice quale sapore dell'unione è attivo.

In nessuno di questi casi è possibile ignorare ciecamente l'unione e convertirla in una struttura in cui i due (o più) campi non coincidono.

In C / C ++ l'unione è usata per sovrapporre membri diversi nella stessa posizione di memoria, quindi se hai un'unione di un int e un float entrambi usano gli stessi 4 byte di memoria per memorizzare, ovviamente scrivendo su uno si corrompe il altro (poiché int e float hanno layout di bit diverso).

In .Net Microsoft ha scelto con maggiore sicurezza e non ha incluso questa funzionalità.

EDIT: ad eccezione dell'interoper

Se stai usando il union per mappare i byte di uno dei tipi sull'altro, in C # puoi invece usare BitConverter .

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

o;

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

Personalmente, ignorerei tutti insieme l'UNIONE e implementerei Killroy e Fubar come campi separati

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

L'uso di UNION consente di risparmiare 32 bit di memoria allocati da int .... al momento non creeremo o distruggeremo un'app.

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

    public float fubar
    {
        get{ return (float)killroy;}
        set{ killroy = (int)value;}
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top