307

I'm testing out some WCF services that send objects with Guids back and forth. In my web app test code, I'm doing the following:

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

For some reason, the call to new Guid() is generating Guids with all 0's (zeros) like this:

00000000-0000-0000-0000-000000000000

What could be causing this?

Didaxis
  • 8,486
  • 7
  • 52
  • 89

6 Answers6

517

Use the static method Guid.NewGuid() instead of calling the default constructor.

var responseObject = proxy.CallService(new RequestObject
{
    Data = "misc. data",
    Guid = Guid.NewGuid()
});
Mark Byers
  • 811,555
  • 193
  • 1,581
  • 1,452
122

Lessons to learn from this:

1) Guid is a value type, not a reference type.

2) Calling the default constructor new S() on any value type always gives you back the all-zero form of that value type, whatever it is. It is logically the same as default(S).

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
  • 3
    Does it compile into the same IL as `default(S)` or are there any subtleties I'm missing? – configurator Nov 02 '11 at 19:02
  • 8
    @configurator: It does. In fact, the compiler's internal representation of "default(S)" and "new S()" are the same; we do not distinguish them internally, which has led to some unfortunate bugs over the years because they are in fact not *quite* identical. For example, `const int x = new int();` is not supposed to be legal according to the spec, but `const int x = default(int);` is; we allow both. – Eric Lippert Nov 07 '11 at 19:04
  • 1
    @configurator - if you're interested in related corner cases, perhaps http://msmvps.com/blogs/jon_skeet/archive/2008/12/10/value-types-and-parameterless-constructors.aspx would also be of interest. – kvb Nov 07 '11 at 19:46
59

Try this instead:

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

This will generate a 'real' Guid value. When you new a reference type, it will give you the default value (which in this case, is all zeroes for a Guid).

When you create a new Guid, it will initialize it to all zeroes, which is the default value for Guid. It's basically the same as creating a "new" int (which is a value type but you can do this anyways):

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

Compare this to doing the same thing with an int:

int i1;                     // i1 is 0
int i2 = new int();         // i2 is 0
int i3 = default(int);      // i3 is 0
JohnD
  • 14,327
  • 4
  • 40
  • 53
  • 1
    `g1` will only compile as field and not as local variable. Also the indices in your comment column don't match up with the same line of the code – CodesInChaos Nov 01 '11 at 22:02
  • 1
    @CodeInChaos: Thanks, fixed the comments. FYI, the g1 line does actually compile... – JohnD Nov 01 '11 at 23:43
  • 3
    It will compile as is, but it has no defined value. If you add code that reads it (before writing to it) it will not compile anymore. – CodesInChaos Nov 01 '11 at 23:58
  • 1
    Right, good point, you will get an error if you use an uninitialized variable, so the value cannot be used. – JohnD Nov 02 '11 at 01:35
  • 1
    down-voted because the line "Guid = Guid.NewGuid();" may confuse newer developers. Consider editing to something like "Guid someGuid = Guid.NewGuid();" like the g2 line ;) – daviesdoesit Jan 09 '19 at 18:14
  • 1
    @daviesdoesit that line was meant to replace the line from the question (where they are setting the property named "Guid"). I added the sample code which should make it clearer – JohnD Jan 09 '19 at 20:53
  • 1
    To be more clear, in your sample code, you are using GUID like a type. public static void Main() { Console.WriteLine("Hello World"); // Guid = Guid.NewGuid(); // this fails: "Guid" is a type but is used like a variable. Guid someGuid = Guid.NewGuid(); Console.WriteLine(someGuid ); // yields a usable Guid as expected. } – daviesdoesit Jan 17 '19 at 18:10
  • 1
    Additionally, the line with g1 may compile, but does not (as your comment on the same line may suggest) yield a blank Guid of all zeroes; As you noted (and in above answers) the Guid is a reference type and must be instantiated, hence the Guid.NewGuid() requirement. If you tried to use g1 prior to assigning it a value it would error out. In a new dotnetfiddle try the following: Guid g1; Console.WriteLine(g1); // Use of unassigned local variable – daviesdoesit Jan 17 '19 at 18:15
  • 2
    There's a 'new' too many in 'Guid = *new* Guid.NewGuid()', the 4th line of the first example. It must have wound up in there in an edit, because I can't believe it took 8 years for someone to notice that. And I think there's something wrong with the next paragraph, "when you 'new' a reference type, it will give you the default value". Guid is a value type. – Luc VdV Apr 23 '19 at 08:10
32

Try doing:

Guid foo = Guid.NewGuid();
Dylan Smith
  • 22,069
  • 2
  • 47
  • 62
19

Can't tell you how many times this has caught. me.

Guid myGuid = Guid.NewGuid(); 
Matt Dawdy
  • 19,247
  • 18
  • 66
  • 91
12

In the spirit of being complete, the answers that instruct you to use Guid.NewGuid() are correct.

In addressing your subsequent edit, you'll need to post the code for your RequestObject class. I'm suspecting that your guid property is not marked as a DataMember, and thus is not being serialized over the wire. Since default(Guid) is the same as new Guid() (i.e. all 0's), this would explain the behavior you're seeing.

Adam Robinson
  • 182,639
  • 35
  • 285
  • 343