为什么.NET GUID中会有破折号?

67

为什么 .NET GUID 中有连字符?大部分实现 GUID 的程序中是否都有连字符,还是只有微软的实现有?

谢谢,

741ecf77-9c92-4435-8e6b-85975bd13452


有趣的问题。我必须说,我从未停下来思考过它。 - Jason Baker
GUIDs的熵值数量不受其是否带有连字符的影响。 - recursive
连字符只用于将 UUID 以文本形式显示时。真正的 UUID 是一个由 16 个字节组成的二进制字符串/数组。 - Bart van Heukelom
13个回答

65

从技术上讲,在GUID中没有“破折号”。 GUID是一个128位的值,通常以以下方式存储(这里使用C#表示结构):

public struct Guid
{
  public ulong Data1;
  public ushort Data2;
  public ushort Data3;
  public fixed byte Data4[8];
}

破折号是GUID的字符串表示形式中的一部分。

破折号是可选的,在GUID的字符串表示形式中不是必需的。

尽管如此,历史原因决定了破折号的位置,这与GUID的生成方式有关,但这种历史语义已不再适用。


3
这完全是错误的,GUID 的连字符 ASCII Hex 表示中有 5 个连字符元素,包含二进制 GUID 元素的结构体只有 4 个元素。此外,历史语义在这个问题中仍然适用,特别是考虑到历史正是为什么首先出现连字符的原因。 - joshperry
2
@joshperry,你重申了我的答案。Guid只是128个字节,没有别的。分隔符来自表示。此外,在表示中适用于历史语义的内容已经不再适用。正如你所说,这是出于历史原因。那些历史原因已经不再适用。从你的回答中可以看出,“这些数据元素不再具有任何特定的含义。” - casperOne
2
我不确定在哪里重申了GUID是128字节,但你的第二段(关于连字符与结构对应)显然是不准确的。连字符之所以存在,是因为该布局在UUID RFC中有明确规定,与该结构无关。当代UUID中的段不一定意味着它们曾经意味着什么,但它们之所以存在是因为它们曾经意味着什么。所以我想现在它们存在是因为RFC这样规定,如果你想/需要创建可互操作的URN,则必须遵循RFC。 - joshperry
1
@joshperry 删除了关于破折号位置的部分,并保留了它们是可选的方式。这应该满足您的要求。 - casperOne

45
在 UUID(通用唯一标识符)规范的最初版本中,每个数据元素都具有语义含义:
{ time_low } - { time_mid } - { time_high_and_version } - { clock_seq_and_reserved clock_seq_low } - { node_id }
这些元素旨在提供时间(时间位)和空间(主机位)上的唯一性。
版本历史
由于在2 ^ 1024随机位的键空间中发生冲突的数学概率被认为是极其不可能的,UUID规范的后续版本已经淘汰了时间和主机数据以保护安全和隐私。
唯一保留任何含义的元素是版本位和保留位。
版本3的UUID是从URI或其他可识别名称的MD5哈希派生而来的。
版本4使用随机数据生成,目前是您在野外看到的最常见实现。
版本5是从SHA1哈希派生而来的。
存储格式
由于连字符在RFC中指定为UUID的ASCII格式化,即使各个部分不再保留其原始含义,如果您需要互操作性,则仍然需要它们。
UUID有时还作为Base64或ascii85编码的字符串存储,以节省在不支持二进制的传输中的空间,并且不需要遵守RFC。
Ascii:   3F2504E0-4F89-11D3-9A0C-0305E82C3301
Base64:  7QDBkvCA1+B9K/U0vrQx1A
Ascii85: 5:$Hj:Pf\4RLB9%kU\Lj

参考资料:
RFC4122(特别是第3页的ABNF描述UUID格式)
维基百科 GUID UUID


14

您可以以多种格式获取您的 GUID。

假设您正在使用 C#:

Guid guid = Guid.NewGuid();

Console.WriteLine(guid.ToString("N"))

63be6f7e4e564f0580229f958f492077

Console.WriteLine(guid.ToString("D"))

63be6f7e-4e56-4f05-8022-9f958f492077

Console.WriteLine(guid.ToString("B"))

{63be6f7e-4e56-4f05-8022-9f958f492077}

Console.WriteLine(guid.ToString("P"))

(63be6f7e-4e56-4f05-8022-9f958f492077)


"D"是默认值。另请参考:https://learn.microsoft.com/en-us/dotnet/api/system.guid.tostring?view=net-8.0 - Jonas Äppelgran

13

连字符表示 Guid 的字节结构。

typedef struct _GUID 
{  
   DWORD Data1;  
   WORD Data2;  
   WORD Data3;  
   BYTE Data4[8];
} GUID;

对于:

(XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX)

在保存之前,您可能可以删除它们。至少在.NET中,Guid类型的构造函数将从其字符串表示形式初始化一个Guid变量,无论连字符是否存在或被删除。


那是真的,但你不能以任何有意义的方式使用该结构的部分,对吧? - sharptooth
但是为什么在 Data4 中有额外的连字符? - dan04
请查看此处的解释:http://en.wikipedia.org/wiki/Globally_unique_identifier - user151323

9

6

4

我看到的几乎所有GUID的可视化表示都使用虚线格式。这种格式更容易阅读。


3

.NET中的Guid类可以识别多种格式:使用破折号作为分隔符、没有分隔符、使用方括号和圆括号作为分隔符或者没有分隔符等。


更正一下,Guid 不是一个类,而是一个值类型。 - casperOne

2

连字符用于分隔每个数字

E93416C5-9377-4A1D-8390-7E57D439C9E7

Hex digits  Description
8           Data1
4           Data2
4           Data3
4           Initial two bytes from Data4
12          Remaining six bytes from Data4

1

这只是为了方便而已。GUID由16个字节组成,可以用32个十六进制字符表示。没有连字符,GUID对人类来说更难以感知,并且更难被识别为GUID而不是一些随机的16字节数字。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接