Вопрос
Я перевожу библиотеку, написанную на C ++, на C #, и ключевое слово 'union' существует один раз.В структуре.
Как правильно перевести это на C #?И что же он делает?Выглядит это примерно так;
struct Foo {
float bar;
union {
int killroy;
float fubar;
} as;
}
Решение
Для этого вы можете использовать явные макеты полей:
[StructLayout(LayoutKind.Explicit)]
public struct SampleUnion
{
[FieldOffset(0)] public float bar;
[FieldOffset(4)] public int killroy;
[FieldOffset(4)] public float fubar;
}
Непроверенный.Идея заключается в том, что две переменные имеют одинаковое положение в вашей структуре.Конечно, вы можете использовать только один из них.
Более подробная информация о профсоюзах в учебное пособие по созданию структуры
Другие советы
Вы действительно не можете решить, как с этим бороться, не зная кое-что о том, как это используется.Если он просто используется для экономии места, то вы можете проигнорировать его и просто использовать struct .
Однако обычно союзы используются не для этого.Есть две распространенные причины их использования.Один из них заключается в предоставлении 2 или более способов доступа к одним и тем же данным.Например, объединение int и массива из 4 байт является одним (из многих) способов разделения байтов 32-битного целого числа.
Другой случай, когда данные в структуре поступают из внешнего источника, такого как сетевой пакет данных.Обычно одним элементом структуры, заключающей объединение, является идентификатор, который сообщает вам, какой вариант объединения действует.
Ни в одном из этих случаев вы не можете слепо игнорировать объединение и преобразовать его в структуру, в которой два (или более) поля не совпадают.
В C / C ++ объединение используется для наложения разных элементов в одной и той же ячейке памяти, поэтому, если у вас есть объединение int и float, они оба используют одни и те же 4 байта памяти для хранения, очевидно, что запись в один портит другой (поскольку int и float имеют разную разрядность).
В .Net Microsoft выбрала более безопасный вариант и не включила эту функцию.
Редактировать:за исключением взаимодействия
Если вы используете union
чтобы сопоставить байты одного из типов с другими, тогда в C # вы можете использовать BitConverter
вместо этого.
float fubar = 125f;
int killroy = BitConverter.ToInt32(BitConverter.GetBytes(fubar), 0);
или;
int killroy = 125;
float fubar = BitConverter.ToSingle(BitConverter.GetBytes(killroy), 0);
Лично я бы проигнорировал ОБЪЕДИНЕНИЕ всех вместе и реализовал Killroy и Fubar как отдельные поля
public struct Foo
{
float bar;
int Kilroy;
float Fubar;
}
Использование ОБЪЕДИНЕНИЯ экономит 32 бита памяти, выделенной int .... в наши дни приложение не будет создавать или прерывать работу.
public class Foo
{
public float bar;
public int killroy;
public float fubar
{
get{ return (float)killroy;}
set{ killroy = (int)value;}
}
}