正如其他人所提到的,您可以使用 BitConverter 类,尽管他们未能在实际代码中考虑字节序(只是在最后简要提及):
public static (byte Hibyte, byte Lobyte) GetBytes(short i)
{ // This is my recommendation; it gets both bytes in one call, so it
// may be more efficient.
var bytes = BitConverter.GetBytes(i);
if (BitConverter.IsLittleEndian)
Array.Reverse(bytes)
return (bytes[0], bytes[1]);
}
public static (byte Hibyte, byte Lobyte) GetBytes(ushort i)
{ // BitConverter works equally well with unsigned types.
var bytes = BitConverter.GetBytes(i);
if (BitConverter.IsLittleEndian)
Array.Reverse(bytes)
return (bytes[0], bytes[1]);
}
public static byte Hibyte(short i)
{ // If you want to use your original schema, here's the hi byte:
if (BitConverter.IsLittleEndian)
return BitConverter.GetBytes()[1];
return BitConverter.GetBytes()[0];
}
public static byte Hibyte(ushort i)
{ // Again, same thing works for ushort
if (BitConverter.IsLittleEndian)
return BitConverter.GetBytes()[1];
return BitConverter.GetBytes()[0];
}
public static short MakeShort(byte hb, byte lb)
{
byte[] bytes = new byte[] { hb, lb };
if (BitConverter.IsLittleEndian)
Array.Reverse(bytes);
return BitConverter.ToInt16(bytes);
}
public static ushort MakeUShort(byte hb, byte lb)
{
byte[] bytes = new byte[] { hb, lb };
if (BitConverter.IsLittleEndian)
Array.Reverse(bytes);
return BitConverter.ToUInt16(bytes);
}
而且,虽然其他人提到使用 unchecked,但他们忽略了一个问题:正如您在原始问题中指出的那样,当对有符号整数类型进行右移时,符号位会重复,所以虽然这有效:
public static byte Hibyte(ushort i)
{ return (byte)(i >> 8); }
// No need for unchecked, because result will always fit in one byte and is never < 0.
public static byte Lobyte(ushort i)
{ return (byte)(i & 0xFF); } // No need for unchecked for the same reason.
public static byte LoByte(short i)
{ return (byte)(i & 0xFF); }
// Like above, no need for unchecked for the same reasons; also, bitwise & works the same
// for both signed and unsigned types.
public static ushort MakeUShort(byte hb, byte lb)
{ return (ushort)((hb << 8) | lb); }
// Again, no need for unchecked; result is always 16 bits and never negative.
public static short MakeShort(byte hb, byte lb)
{ unchecked { return (short)((hb << 8) | lb); } }
// This time, we may need unchecked because result may overflow short.
...为 signed short 的高字节给出的代码需要额外的转换:
public static byte Hibyte(short i)
{ unchecked { return (byte)((ushort)i >> 8); } }
// Again, the unchecked is needed, this time because i may be negative,
// which may need to be accounted for when casting to a ushort.
通过在移位之前将有符号的short 转换为无符号的ushort,我们可以防止符号位被添加到前面 8 次。或者,我们可以使用按位 & 来忽略传播的符号位:
public static byte HiByte (short i)
{ return (byte)((i >> 8) & 0xFF); }
// Since bitwise operations never result in overflow, and by the time we cast at the end,
// the number is guaranteed to fit in a byte and be >= 0, we no longer need any unchecked blocks.
其中任何一个都会产生相同的结果。