Объединение С++ в С#

Я перевод библиотеки, написанной на С++, на С#, и ключевое слово 'union' существует один раз. В структуре.

Каков правильный способ перевода его на С#? И что он делает? Это выглядит примерно так:

struct Foo {
    float bar;

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

Ответ 1

Для этого можно использовать явные поля:

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

непроверенная. Идея состоит в том, что две переменные имеют одинаковую позицию в вашей структуре. Конечно, вы можете использовать только один из них.

Дополнительная информация о союзах в struct tutorial

Ответ 2

Вы не можете решить, как с этим справиться, не зная о том, как он используется. Если это просто используется для экономии места, вы можете игнорировать его и просто использовать struct.

Однако обычно это не означает, что используются союзы. Существуют две общие причины их использования. Один из них заключается в предоставлении двух или более способов доступа к тем же данным. Например, объединение int и массив из 4 байтов - это один (из многих) способов выделения байтов из 32-битного целого числа.

Другой - когда данные в структуре поступают из внешнего источника, такого как сетевой пакет данных. Обычно один элемент структуры, охватывающий объединение, - это идентификатор, который сообщает вам, какой аромат объединения действует.

В любом из этих случаев вы не можете слепо проигнорировать объединение и преобразовать его в структуру, где два (или более) поля не совпадают.

Ответ 3

В C/С++ union используется для наложения разных членов в одно и то же место памяти, поэтому, если у вас есть объединение int и flat, они оба используют те же 4 байта памяти, очевидно, что запись на один развращает другую ( поскольку int и float имеют разную компоновку бит).

В .net MS пошел с более безопасным выбором и не включил эту функцию.

EDIT: кроме interop

Ответ 4

Лично я буду игнорировать UNION вместе и реализовать Killroy и Fubar как отдельные поля

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

Использование UNION сохраняет 32 бита памяти, выделенных int.... не собирается делать или прерывать приложение в эти дни.

Ответ 5

Если вы используете union для сопоставления байтов одного из типов с другим, а затем на С#, вы можете использовать BitConverter вместо этого.

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

или

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