Guid ist alle Nullen (Nullen)?

241

Ich teste einige WCF-Dienste, die Objekte mit Guids hin und her senden. In meinem Web-App-Testcode mache ich Folgendes:

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

Aus irgendeinem Grund generiert der Aufruf von new Guid () Guids mit allen Nullen (Nullen) wie folgt:

00000000-0000-0000-0000-000000000000

Was könnte das verursachen?

Didaxis
quelle
9
Nach Ihrer Bearbeitung ist dies eine völlig neue Frage. Und es werden viel mehr Informationen benötigt, um die neue Antwort zu bestimmen.
Scott Rippey
3
Der bearbeitete Teil, der die Frage geändert hat, wurde entfernt.
Didaxis
115
+1 weil ich diese Frage benutzt habe, um ein Dutzend Mal einen leeren Guid zu stehlen :)
jmosesman
5
@jmosesman, es ist besser, das Formular zu verwendenGuid.Empty
Jonathan Moosekian
4
@ JonathanM Ich verwende es tatsächlich in einem SQL-Skript. Dieser Beitrag wird erst nach der Suche angezeigt.
jmosesman

Antworten:

428

Verwenden Sie die statische Methode, Guid.NewGuid()anstatt den Standardkonstruktor aufzurufen.

var responseObject = proxy.CallService(new RequestObject
{
    Data = "misc. data",
    Guid = Guid.NewGuid()
});
Mark Byers
quelle
18
+1 für die richtige Antwort sowie einen Link zur richtigen Dokumentation.
ObscureRobot
109

Lehren daraus:

1) Guid ist ein Werttyp, kein Referenztyp.

2) Wenn Sie den Standardkonstruktor new S()für einen beliebigen Werttyp aufrufen, erhalten Sie immer die Nullform dieses Werttyps zurück, unabhängig davon, um welchen Wert es sich handelt. Es ist logisch dasselbe wie default(S).

Eric Lippert
quelle
3
Kompiliert es in dieselbe IL wie default(S)oder fehlen mir Feinheiten?
Konfigurator
8
@configurator: Das tut es. Tatsächlich ist die interne Darstellung von "default (S)" und "new S ()" durch den Compiler identisch. Wir unterscheiden sie nicht intern, was im Laufe der Jahre zu einigen unglücklichen Fehlern geführt hat, da sie tatsächlich nicht ganz identisch sind. Zum Beispiel const int x = new int();soll laut Spezifikation nicht legal sein, ist es aber const int x = default(int);; wir erlauben beides.
Eric Lippert
1
@configurator - Wenn Sie an verwandten Eckfällen interessiert sind, ist möglicherweise auch msmvps.com/blogs/jon_skeet/archive/2008/12/10/… von Interesse.
KVB
56

Versuchen Sie stattdessen Folgendes:

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

Dies erzeugt einen "echten" Guid-Wert. Wenn Sie einen Referenztyp neu erstellen, erhalten Sie den Standardwert (in diesem Fall alle Nullen für eine Guid).

Wenn Sie eine neue Guid erstellen, wird sie mit allen Nullen initialisiert. Dies ist der Standardwert für Guid. Es ist im Grunde dasselbe wie das Erstellen eines "neuen" Int (was ein Werttyp ist, aber Sie können dies trotzdem tun):

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

Vergleichen Sie dies damit, dass Sie dasselbe mit einem int tun:

int i1;                     // i1 is 0
int i2 = new int();         // i2 is 0
int i3 = default(int);      // i3 is 0
JohnD
quelle
1
g1wird nur als Feld und nicht als lokale Variable kompiliert. Auch die Indizes in Ihrer Kommentarspalte stimmen nicht mit der gleichen Codezeile
überein
1
@ CodeInChaos: Danke, die Kommentare wurden korrigiert. Zu
Ihrer Information
3
Es wird so kompiliert, wie es ist, aber es hat keinen definierten Wert. Wenn Sie Code hinzufügen, der ihn liest (bevor Sie darauf schreiben), wird er nicht mehr kompiliert.
CodesInChaos
1
Richtig, guter Punkt, Sie erhalten eine Fehlermeldung, wenn Sie eine nicht initialisierte Variable verwenden, sodass der Wert nicht verwendet werden kann.
JohnD
1
herabgestimmt, weil die Zeile "Guid = Guid.NewGuid ();" kann neuere Entwickler verwirren. Überlegen Sie, ob Sie etwas wie "Guid someGuid = Guid.NewGuid ();" wie die g2 Linie;)
daviesdoesit
25

Versuchen Sie Folgendes:

Guid foo = Guid.NewGuid();
Dylan Smith
quelle
1
Grund für die Ablehnung: "Guid" ist ein Typ, wird aber wie eine Variable verwendet.
Daviesdoesit
19

Ich kann dir nicht sagen, wie oft das gefangen hat. mich.

Guid myGuid = Guid.NewGuid(); 
Matt Dawdy
quelle
11

Im Sinne der Vollständigkeit sind die Antworten, die Sie anweisen, Guid.NewGuid()richtig zu sein.

Um Ihre nachfolgende Bearbeitung zu adressieren, müssen Sie den Code für Ihre RequestObjectKlasse veröffentlichen. Ich vermute, dass Ihre Guid-Eigenschaft nicht als gekennzeichnet DataMemberist und daher nicht über das Kabel serialisiert wird. Da dies default(Guid)dasselbe ist wie new Guid()(dh alle 0), würde dies das Verhalten erklären, das Sie sehen.

Adam Robinson
quelle