C ++ объединение в C # - PullRequest
       70

C ++ объединение в C #

65 голосов
/ 24 сентября 2008

Я перевожу библиотеку, написанную на C ++, на C #, и ключевое слово «union» существует один раз. В структуре.

Как правильно перевести его на C #? И что это делает? Это выглядит примерно так;

struct Foo {
    float bar;

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

Ответы [ 6 ]

72 голосов
/ 24 сентября 2008

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

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

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

Больше информации о союзах в Руководство по структуре

21 голосов
/ 24 сентября 2008

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

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

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

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

3 голосов
/ 24 сентября 2008

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

В .Net Microsoft выбрала более безопасный вариант и не включила эту функцию.

РЕДАКТИРОВАТЬ: за исключением взаимодействия

1 голос
/ 21 сентября 2016

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

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

или *; 1006 *

int killroy = 125;
float fubar = BitConverter.ToSingle(BitConverter.GetBytes(killroy), 0);
1 голос
/ 24 сентября 2008

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

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

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

0 голосов
/ 29 июня 2018
public class Foo
{
    public float bar;
    public int killroy;

    public float fubar
    {
        get{ return (float)killroy;}
        set{ killroy = (int)value;}
    }
}
...