Guid是全部为0的吗?

313

我正在测试一些通过 WCF 发送包含 GUID 的对象的服务。在我的 Web 应用程序测试代码中,我正在执行以下操作:

var responseObject = proxy.CallService(new RequestObject
{
    Data = "misc. data",
    Guid = new Guid()
});

由于某种原因,调用 new Guid() 方法生成的 Guid 全部都是 0 (零) ,像这样:

00000000-0000-0000-0000-000000000000

可能是什么原因导致这种情况?


1
重叠:http://stackoverflow.com/q/7972658/60761 - H H
181
+1 是因为我已经用这个问题偷了十几次空白的 GUID :) (注:GUID 是全局唯一标识符,是一种软件开发中常用的标识符) - jmosesman
6个回答

518

使用静态方法Guid.NewGuid()代替调用默认构造函数。

var responseObject = proxy.CallService(new RequestObject
{
    Data = "misc. data",
    Guid = Guid.NewGuid()
});

24
对于正确答案的回答打+1,同时提供正确文档的链接。 - ObscureRobot

122

从中学到的教训:

1) Guid 是值类型而非引用类型。

2) 在任何值类型上调用默认构造函数new S()总是会给你返回该值类型的全零形式,无论它是什么。这在逻辑上等同于default(S)


3
它是否编译成与 default(S) 相同的IL代码,或者我有遗漏的微妙之处吗? - configurator
8
@configurator: 的确如此。事实上,编译器对 "default(S)" 和 "new S()" 的内部表示是相同的;我们在内部不加区分它们,这在多年来导致了一些不幸的错误,因为它们实际上并不完全相同。例如,根据规范,const int x = new int(); 不应该合法,但 const int x = default(int); 是可以的;我们允许两者。 - Eric Lippert
1
@configurator - 如果你对相关的边角案例感兴趣,也许 http://msmvps.com/blogs/jon_skeet/archive/2008/12/10/value-types-and-parameterless-constructors.aspx 也会引起你的兴趣。 - kvb

60

可以尝试这个:

var responseObject = proxy.CallService(new RequestObject
{
    Data = "misc. data",
    Guid = new Guid.NewGuid()
});

这将生成一个“真实”的Guid值。当您new一个引用类型时,它会给您默认值(在这种情况下,对于Guid来说,是全部为零)。

当您创建一个新的Guid时,它将初始化为全部为零,这是Guid的默认值。它基本上与创建“new”int相同(这是一个值类型,但您仍然可以这样做):

Guid g1;                    // g1 is 00000000-0000-0000-0000-000000000000
Guid g2 = new Guid();       // g2 is 00000000-0000-0000-0000-000000000000
Guid g3 = default(Guid);    // g3 is 00000000-0000-0000-0000-000000000000
Guid g4 = Guid.NewGuid();   // g4 is not all zeroes

将其与使用int完成相同操作进行比较:

int i1;                     // i1 is 0
int i2 = new int();         // i2 is 0
int i3 = default(int);      // i3 is 0

3
它将按原样编译,但它没有定义的值。如果您添加读取它的代码(在写入之前),它将不再编译。 - CodesInChaos
1
@daviesdoesit,那行代码的目的是替换问题中设置名为“Guid”的属性的那一行。我添加了示例代码,应该会更清晰明了。 - JohnD
1
更明确地说,在您的示例代码中,您正在使用GUID作为类型。 public static void Main() { Console.WriteLine("Hello World"); // Guid = Guid.NewGuid(); // 这会失败:“Guid”是一种类型,但像变量一样使用。 Guid someGuid = Guid.NewGuid(); Console.WriteLine(someGuid ); // 产生预期的可用Guid。 } - daviesdoesit
1
此外,带有g1的那一行可能会编译通过,但不会(正如您在同一行上的评论所建议的那样)产生全零的空Guid;正如您注意到的(以及上面的答案),Guid是一个引用类型,必须被实例化,因此需要Guid.NewGuid()。如果您在分配值之前尝试使用g1,则会出现错误。在新的dotnetfiddle中尝试以下操作: Guid g1; Console.WriteLine(g1); // 使用未分配的本地变量 - daviesdoesit
2
在第一个示例的第4行“Guid = new Guid.NewGuid()”中,有一个多余的“new”,这可能是在编辑过程中误加进去的,因为我无法相信8年里没有人注意到这个问题。而且我认为下一段文字存在问题,“当你‘new’一个引用类型时,它会给你默认值”。Guid是一个值类型。 - Luc VdV
显示剩余4条评论

33

尝试执行以下操作:

Guid foo = Guid.NewGuid();

1
下降投票的原因:“Guid”是一种类型,但被用作变量。 - daviesdoesit

19

我无法告诉你这已经抓住了我多少次。

Guid myGuid = Guid.NewGuid(); 

12

为了全面,建议你使用 Guid.NewGuid() 的答案是正确的。

针对你后来编辑的内容,你需要发布你的 RequestObject 类的代码。我怀疑你的 guid 属性没有标记为 DataMember,因此没有在网络上传输中被序列化。由于 default(Guid)new Guid()(即所有 0)相同,这可以解释你所看到的行为。


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