C # Байт и приведение битов - это может быть сделано лучше? - PullRequest
2 голосов
/ 24 мая 2011

Я строю массивы байтов для связи по Bluetooth. Эти байты частично построены из перечислимых типов, таких как следующие:

public enum Motor
{
   A = 0x00,
   B = 0x01,
   C = 0x02,
   AB = 0x03,
   AC = 0x04,
   BC = 0x05,
}

Позже в моем коде я создаю переменную с именем MyMotor типа MyMotor.B. Затем я передаю эту переменную методу, в котором я строю свой байтовый массив.

Моя проблема в том, что программное обеспечение, с которым я общаюсь через Bluetooth, ожидает шестнадцатеричное значение перечисленного значения в виде строки, т.е. MyMotor.B = байт 0x01 = dec 1 = hex 31. Однако приведение MyMotor непосредственно к символу приведите его к его перечисляемому значению, т.е. MyMotor = B = hex 42.

По разным причинам я не могу изменить свой исчерпывающий список, поэтому я остановился на том, что похоже на очень взломанный вместе двухстрочный фрагмент кода:

String motorchar = Convert.ToString(Convert.ToInt32(MyMotor)); // convert to temp var
command[5] = (byte)(motorchar[0]); // store hex value of var

Это работает так, как я хотел бы, т.е. команда [5] = hex31

Интересно, есть ли лучший способ? Все статьи, которые я нашел, говорят о работе с целыми байтовыми массивами, а не с отдельными байтами и символами.

Ответы [ 5 ]

0 голосов
/ 24 мая 2011

Почему бы не использовать:

//If you want the ASCII representation.
//  e.g. myMotor == B, then the Byte Decimal value will be 49 or 0x31.
command[5] = (byte)((byte)myMotor).ToString()[0];

или

//If you want the numeric representation:
//  e.g. myMotor == B, then the Byte Decimal value will be 1 or 0x01.
command[5] = (byte)myMotor;

Я вижу, вы используете значения, такие как "0x01" и "0x05". Префикс «0x» означает, что это шестнадцатеричное число, но вы никогда не выходите за пределы 5, поэтому оно точно такое же, как использование целочисленных значений «1» и «5».

Я не вижу, как вы получаете десятичную 1 == шестнадцатеричную 31 или шестнадцатеричную 42, которую вы упоминаете в своем посте. ASCII-эквивалент Char '1' равен десятичному 49 или шестнадцатеричному 31.

0 голосов
/ 24 мая 2011

Если вы знаете, что значения вашей программы и ожидаемые API-значения всегда отличаются на определенную фиксированную величину (например, AC = 0x04, но API требует "4"), вы можете написать простое преобразование:

char c = (char)((int)Motor + '0');

Это может показаться некрасивым, когда существует более 10 значений. Вы можете использовать его в особых случаях для шестнадцатеричных цифр, но после этого это довольно плохо.

Вам лучше создать поисктаблица, самым общим из которых является словарь:

Dictionary<Motor, string> MotorLookup = new Dictionary<Motor, string>() {
    { Motor.A, "0" },
    { Motor.B, "1" },
    // etc, etc.
};

Это будет наиболее гибким и наиболее поддерживаемым.

0 голосов
/ 24 мая 2011

Если ваше другое приложение ожидает строку, укажите ее. Создайте массив строк для хранения значений (которые вам известны) и используйте значение int для перечисления в качестве индекса в этом массиве.

0 голосов
/ 24 мая 2011

Если я что-то упустил, ваш двухстрочный код эквивалентен простому звонку;

BitConverter.ToString(MyMotor);

Нет?

0 голосов
/ 24 мая 2011
chars[0] = (char)('0' + ((byte)myMotor & 0x0F));
chars[1] = (char)('0' + (((byte)myMotor & 0xF0) >> 4));

Однако для шестнадцатеричной системы требуется немного больше настроек.

...