Присвоение int объекту структуры без использования unsafe

У меня есть определение структуры в С# следующим образом

public struct test                                                                                  
{
    byte   SetCommonPOP;
    byte   SetCommonSVP;
    byte   SetCommonUHDP;
    byte   SetCommonMHDP;
};

Как присвоить int y объекту x этой структуры без использования unsafe?


person Tyler Durden    schedule 21.10.2013    source источник
comment
Как бы вы хотели, чтобы int интерпретировалось? Различные системы порядка следования байтов могут преобразовываться по-разному.   -  person Jon Skeet    schedule 21.10.2013
comment
И int, и объект struct занимают 4 байта. Предположим, что первый участник получает LSB, а четвертый MSB.   -  person Tyler Durden    schedule 21.10.2013
comment
Это будет большой Endian, верно? Извините, но я всегда путаюсь.   -  person Tyler Durden    schedule 21.10.2013
comment
Я считаю, что на самом деле это прямой порядок байтов: en.wikipedia.org/wiki/Endianness В любом случае, вот почему мой ответ делает это явным - вы всегда можете изменить его :)   -  person Jon Skeet    schedule 21.10.2013
comment
Это было бы прямым порядком байтов. Я помню это по истории, которая является источником слов с порядком байтов: те, кто начинает с маленьким концом яйца всмятку имеют прямой порядок байтов, те, кто начинается с большого конца, имеют прямой порядок байтов. Это сбивает с толку, потому что обратный порядок байтов — это не когда вы заканчиваете большими значениями, а когда вы начинаете с большого конца.   -  person Tim S.    schedule 21.10.2013


Ответы (2)


Вы можете написать собственный оператор преобразования:

public struct Test
{
    private readonly byte pop;
    private readonly byte svp;
    private readonly byte uhdp;
    private readonly byte mhdp;

    // TODO: Properties to return the above

    public Test(byte pop, byte svp, byte uhdp, byte mhdp)
    {
        this.pop = pop;
        this.svp = svp;
        this.uhdp = uhdp;
        this.mhdp = mhdp;
    }

    public static implicit operator Test(int value)
    {
        // Working from most significant to least significant bits...
        byte mhdp = (byte) ((value >> 0) & 0xff);
        byte uhdp = (byte) ((value >> 8) & 0xff);
        byte svp = (byte) ((value >> 16) & 0xff);
        byte pop = (byte) ((value >> 24) & 0xff);
        return new Test(pop, svp, uhdp, mhdp);
    }
}

Лично я бы предпочел статический метод FromInt32 вместо неявного оператора, но это ваш выбор. Вполне возможно, что вам не нужны все части & 0xff при преобразовании, и я бы не стал с ними возиться, если бы вы использовали uint вместо int. Извлечение частей целого числа со знаком просто заставляет меня дергаться, и, возможно, это чрезмерная компенсация. Другой альтернативой может быть приведение value к uint в качестве локальной переменной для начала.

person Jon Skeet    schedule 21.10.2013

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

[StructLayout(LayoutKind.Explicit)]
public struct Test
{
    [FieldOffset(3)]
    public readonly byte pop;
    [FieldOffset(2)]
    public readonly byte svp;
    [FieldOffset(1)]
    public readonly byte uhdp;
    [FieldOffset(0)]
    public readonly byte mhdp;

    [FieldOffset(0)]
    private int value;

    public static Test FromInt32(int value)
    {
        var test = new Test();
        test.value = value;
        return test;
    }
}
person Eli Arbel    schedule 21.10.2013
comment
Итак, здесь это рассматривается как объединение со значением члена, занимающим то же место, что и первые 4 члена. Верно? - person Tyler Durden; 21.10.2013
comment
Думаю, тоже должно работать. Единственное, что я не хочу менять определение структуры. В любом случае спасибо - person Tyler Durden; 21.10.2013