C# 字节和位转换 - 这可以做得更好吗?

本文关键字:更好 字节 转换 | 更新日期: 2023-09-27 17:57:18

我正在构建要通过蓝牙通信的字节数组。这些字节部分由枚举类型构建,如下所示:

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

稍后在我的代码中,我创建了一个名为 MyMotor 的变量,类型为 MyMotor.B。然后,我将这个变量传递给我构建字节数组的方法。

我的问题是,我通过蓝牙与之通信的软件期望枚举值的十六进制值为字符串,即 MyMotor.B = 字节 0x01 = dec 1 = 十六进制 31。但是,将 MyMotor 直接转换为字符将导致它评估为其枚举值,即 MyMotor = B = 十六进制 42。

由于各种原因,我无法更改我的列表,因此我选择了感觉像是两行代码非常黑客化的代码部分:

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

它按照我想要的方式工作,即命令[5] = hex31

我想知道是否有更好的方法。我找到的所有文章都在讨论处理整个字节数组,而不是单个字节和字符。

C# 字节和位转换 - 这可以做得更好吗?

chars[0] = (char)('0' + ((byte)myMotor & 0x0F));
chars[1] = (char)('0' + (((byte)myMotor & 0xF0) >> 4));

不过,这需要对十六进制进行更多调整。

如果其他应用需要字符串,请提供一个字符串。创建一个字符串数组来保存值(你知道),并使用枚举的 int 值作为该数组的索引。

除非我错过了什么,否则您的两行代码相当于只是调用;

BitConverter.ToString(MyMotor);

不?

如果您知道程序的值和 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.
};

这将是最灵活和最易于维护的。

为什么不使用:

//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。 字符"1"的 ASCII 等效值是十进制 49 或十六进制 31。