为啥 .NET GUID 中有破折号?

Posted

技术标签:

【中文标题】为啥 .NET GUID 中有破折号?【英文标题】:Why are there dashes in a .NET GUID?为什么 .NET GUID 中有破折号? 【发布时间】:2011-04-03 05:04:16 【问题描述】:

为什么 .NET GUID 中有破折号? GUID 的大多数实现中是否有破折号,或者它只是 Microsoft 的东西?

签名,

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

【问题讨论】:

有趣的问题。我必须说我从来没有停下来思考过。 GUID 具有相同的熵,无论它们是否包含连字符。 连字符仅在显示为文本时使用。真正的 UUID 是一个 16 字节的二进制字符串/数组。 【参考方案1】:

在 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(UUID 格式的 ABNF 描述请参见第 3 页) ***GUIDUUID

【讨论】:

【参考方案2】:

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

public struct Guid

  public ulong Data1;
  public ushort Data2;
  public ushort Data3;
  public fixed byte Data4[8];

破折号在 GUID 的 字符串表示中。

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

也就是说,there are historical reasons as to where the placement of the dashes are,与 GUID 的生成方式有关,但该历史语义不再适用。

【讨论】:

这完全不正确,GUID的连字符ASCII十六进制表示中有5个连字符元素,包含二进制GUID元素的结构只有4个元素长。此外,历史语义肯定确实仍然适用,尤其是在这个问题中,考虑到历史是连字符首先出现的确切原因。 @joshperry 您已经从答案中重申了我的观点。 Guid 只有 128 个字节,句号。分隔符来自representation。此外,关于应用于 representation 的历史语义,它们没有。正如你所说,这是出于历史原因。这些历史原因不再适用。根据您的回答,“这些数据元素不再具有任何特定含义。” 我不确定我在哪里重申 GUID 是 128 个字节,但是您的第二段(关于与结构对应的连字符)显然不准确。有连字符因为布局是在 UUID RFC 中指定的,并且与该结构无关。诚然,当代 UUID 中的片段并不一定意味着它们过去的含义,但是,由于它们过去的含义,它们存在。所以我猜他们现在在那里,因为 RFC 是这么说的,如果您想要/需要创建可互操作的 URN,那么您将遵循 RFC。 @joshperry 删除了关于短划线位置的部分,并保留了它们是可选的。这应该满足你的观点。【参考方案3】:

.NET 的Guid 类可识别多种不同格式:破折号作为分隔符、无分隔符、括号作为分隔符、括号作为分隔符、无分隔符等

【讨论】:

更正,Guid 不是一个类,它是一个值类型。【参考方案4】:

您可以获得各种格式的指南。

假设您使用的是 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)

【讨论】:

【参考方案5】:

连字符对值的唯一性或随机性绝对没有影响。它们只是对 GUID 定义的保留,并在视觉上将构成 GUID 的数据的四个不同部分分开。

【讨论】:

【参考方案6】:

GUID 实际上只是一个数字。连字符向您展示了各种组件是如何分解的,但实际上并不是数字的一部分。它就像一个 IP 地址——你可以存储一个 32 位的数字,也可以存储一个带有点的字符串,它们是等价的。

【讨论】:

【参考方案7】:

连字符用于分隔每个数字

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

【讨论】:

【参考方案8】:

如果您想在某处存储 guid,请将其存储为 16 字节的数组,而不是其文本表示形式。您将节省大量空间,并且不会出现连字符的问题。

【讨论】:

【参考方案9】:

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

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

为:

(XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX)

您可能可以在保存之前剥离它们。至少在 .NET 中,Guid 类型的构造函数将从其字符串表示中初始化 Guid 变量,而不管连字符是否仍然存在或已删除。

【讨论】:

嗯,没错,但你不能以任何有意义的方式使用该结构的一部分,对吗? 但是为什么Data4中的额外连字符? 看这里解释:en.wikipedia.org/wiki/Globally_unique_identifier【参考方案10】:

这只是为了方便。 GUID 由 16 个字节组成,以十六进制文本表示形式由 32 个字符组成。没有连字符的 GUID 更难被人类感知,也更难被识别为 GUID,而不是一些随机性质的 16 字节数字。

【讨论】:

【参考方案11】:

我见过的几乎每一个 guid 的视觉表示都使用虚线格式。这对眼睛来说更容易。

【讨论】:

【参考方案12】:

这是一个分块的例子,就像电话号码、信用卡号码等一样。

Here is a good Wikipedia article about it.

【讨论】:

【参考方案13】:

这只是一种方便。

http://en.wikipedia.org/wiki/GUID

【讨论】:

以上是关于为啥 .NET GUID 中有破折号?的主要内容,如果未能解决你的问题,请参考以下文章

使用 JSON 时如何让 ServiceStack 用破折号格式化 Guid?

为啥 .Net 引用类型中有接口?

ASP.NET Core 产生连续 Guid

ASP.NET中GUID

在 ASP.NET Core 的 URL 查询中使用破折号

Asp.Net Routing - 用生成的 URL 中的破折号替换空格 %20 [重复]