.NET有两种GUID数据类型:Guid,用于命令"自然"中的GUID。方式和SqlGuid,它考虑最后一个破折号后的六个字节是最重要的。这种差异在此详细解释:MSDN: Comparing GUID and uniqueidentifier Values。
但是,在这两种情况下,应该保持以下内容(假设所有...
都相等):
57d0affe-... < 57d0afff-... < 57d0b000-...
如果是这种情况,为什么我会得到以下输出(见注释)?
using System;
using System.Data.SqlTypes;
class Program
{
static void Main(string[] args)
{
var g1 = new SqlGuid("57d0affe-9d9d-11e4-bec2-e840f2ad1632");
var g2 = new SqlGuid("57d0afff-9d9d-11e4-bec2-e840f2ad1632");
var g3 = new SqlGuid("57d0b000-9d9d-11e4-bec2-e840f2ad1632");
Console.WriteLine(g1 < g2); // prints True
Console.WriteLine(g2 < g3); // prints False <- ?
Console.ReadLine();
}
}
我的理解是g2 < g3
也应该产生True。我是否误解了某些内容,或者这是框架中的一些错误?使用普通Guid
代替SqlGuid
时,输出为True
两倍,如预期的那样。
答案 0 :(得分:2)
实际上,比较是逐字节进行的。所以你要问的第一件事是&#34; 0xff是否小于0x00?&#34;显然,它不是:)
这当然是为什么SQL guid符号是&#34;怪异的&#34; - 它&#34;两次倒转&#34;。我不知道为什么MS SQL中的uniqueidentifier
决定这样做(我假设它允许更好的散列或其他东西),但SqlGuid
必须具有相同的行为,所以它只获取整个byte[]
并逐个接一个字节。第一个字节是第一个字节的最后一个字节,第二个字节是第一个字节的倒数第二个字节等。
修改强>:
要添加更多信息,Microsoft标准GUID结构定义如下:
typedef struct _GUID {
DWORD Data1;
WORD Data2;
WORD Data3;
BYTE Data4[8];
} GUID;
当使用逐字节比较时,前三个组获得native-endianness,而最后一个组始终是big-endian。
这是SQL Server中使用的GUID,也是SqlGuid
模拟的GUID。原生.NET System.Guid
在其CompareTo
方法中执行相同的操作。
RFCC 4122 GUID实际上在big-endian机器上显示相同的行为,唯一的区别是它始终是所有组的大端。据我所知,它根本没有描述任何设计的排序。
比较GUID,除了相等之外并没有多大意义。如果您需要这样做,那么有特殊的GUID(如顺序或基于时间的GUID)可以让您更合理地分配值,同时仍然具有合理的独特性。
由于它没有定义,并且它没有太多意义,逐字节比较或char-by-char是最明显的两个 - 人类期望char-by -char,因为我们看到了这个值,但对于计算机来说,逐字节更合理。但是,更为合理的是逐场调查 - 以及那里发生的事情。
答案 1 :(得分:2)
比较有点复杂。
首先定义了一些订单:
private static readonly int[] x_rgiGuidOrder = new int[16]
{10, 11, 12, 13, 14, 15, 8, 9, 6, 7, 4, 5, 0, 1, 2, 3};
然后有这个方法
private static EComparison Compare(SqlGuid x, SqlGuid y) {
//Swap to the correct order to be compared
for (int i = 0; i < SizeOfGuid; i++) {
byte b1, b2;
b1 = x.m_value [x_rgiGuidOrder[i]];
b2 = y.m_value [x_rgiGuidOrder[i]];
if (b1 != b2)
return(b1 < b2) ? EComparison.LT : EComparison.GT;
}
return EComparison.EQ;
}
然而,这不是整个故事,究竟是什么原因是来自字符串的构造函数:
public SqlGuid(String s) {
m_value = (new Guid(s)).ToByteArray();
}
它创建一个新的GUID,然后使用它的字节表示。
这给了我们以下字节值:
g2 : 255 175 208 87 157 157 228 17 190 194 232 64 242 173 22 50
g3 : 0 176 208 87 157 157 228 17 190 194 232 64 242 173 22 50
我们可以看到255大于0而不是相反。