当您在 .NET 中对 GUID 调用
ToByteArray()
时,与 GUID 的字符串表示形式相比,结果数组中字节的顺序不是您所期望的。例如,对于以下表示为字符串的 GUID:
11223344-5566-7788-9900-aabbccddeeff
ToByteArray()
的结果是这样的:
44, 33, 22, 11, 66, 55, 88, 77, 99, 00, AA, BB, CC, DD, EE, FF
注意前四个字节的顺序是相反的。此外,字节 4 和 5 也被交换,字节 6 和 7 也被交换。但最后 8 个字节的顺序与字符串中表示的顺序相同。
我知道这种情况正在发生。我想知道为什么 .NET 以这种方式处理它。
如果您阅读 GUID 构造函数中的 示例部分,您将找到答案:
创建一个对应于Guid(1,2,3,new byte[]{0,1,2,3,4,5,6,7})
的 Guid。"00000001-0002-0003-0001-020304050607"
a
是一个32位整数,b
是一个16位整数,c
是一个16位整数,d
只是8个字节。
由于
a
、b
和 c
是整数类型而不是原始字节,因此在选择如何显示它们时,它们会受到字节顺序的影响。 GUID 的 RFC (RFC4122) 指出它们应该以大端格式呈现。
我为此编写了一个扩展方法,
byte[] ToByteArrayMatchingStringRepresentation(Guid)
,它使用 BitConverter
考虑字节顺序,并就地更改顺序。
using System;
namespace rm.Extensions;
/// <summary>
/// Guid extensions.
/// </summary>
public static class GuidExtension
{
/// <summary>
/// Returns a 16-element byte array that contains the value of this instance
/// matching its string representation (endian-agnostic).
/// <para></para>
/// See https://stackoverflow.com/questions/9195551/why-does-guid-tobytearray-order-the-bytes-the-way-it-does
/// <remarks>
/// <para></para>
/// Note: The byte[] returned by <see cref="ToByteArrayMatchingStringRepresentation(Guid)"/> will not yield
/// the original Guid with <see cref="Guid(byte[])"/> ctor.
/// </remarks>
/// </summary>
public static byte[] ToByteArrayMatchingStringRepresentation(this Guid guid)
{
var bytes = guid.ToByteArray();
TweakOrderOfGuidBytesToMatchStringRepresentation(bytes);
return bytes;
}
/// <summary>
/// Initializes a new instance of the <see cref="Guid"></see> structure by using the specified array of bytes
/// matching its string representation (endian-agnostic).
/// <para></para>
/// See https://stackoverflow.com/questions/9195551/why-does-guid-tobytearray-order-the-bytes-the-way-it-does
/// <remarks>
/// <para></para>
/// Note: The Guid returned by <see cref="ToGuidMatchingStringRepresentation(byte[])"/> will not yield
/// the original byte[] with <see cref="Guid.ToByteArray()"/>.
/// </remarks>
/// </summary>
public static Guid ToGuidMatchingStringRepresentation(this byte[] bytes)
{
_ = bytes ??
throw new ArgumentNullException(nameof(bytes));
if (bytes.Length != 16)
{
throw new ArgumentException("Length should be 16.", nameof(bytes));
}
TweakOrderOfGuidBytesToMatchStringRepresentation(bytes);
return new Guid(bytes);
}
private static void TweakOrderOfGuidBytesToMatchStringRepresentation(byte[] guidBytes)
{
if (BitConverter.IsLittleEndian)
{
Array.Reverse(guidBytes, 0, 4);
Array.Reverse(guidBytes, 4, 2);
Array.Reverse(guidBytes, 6, 2);
}
}
}
来源:https://github.com/rmandvikar/csharp-extensions/blob/dev/src/rm.Extensions/GuidExtension.cs