Guid est tout 0 (zéros)?

241

Je teste certains services WCF qui envoient des objets avec des allers-retours. Dans mon code de test d'application web, je fais ce qui suit:

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

Pour une raison quelconque, l'appel à new Guid () génère des guides avec tous les 0 (zéros) comme ceci:

00000000-0000-0000-0000-000000000000

Qu'est-ce qui peut causer cela?

Didaxis
la source
9
Après votre montage, c'est une toute nouvelle question. Et beaucoup plus d'informations sont nécessaires pour déterminer la nouvelle réponse.
Scott Rippey
3
Suppression de la partie modifiée qui a changé la question.
Didaxis
116
+1 parce que j'ai utilisé cette question pour voler un guide vierge une douzaine de fois :)
jmosesman
5
@jmosesman, il vaut mieux utiliser le formulaireGuid.Empty
Jonathan Moosekian
4
@JonathanM Je l'utilise en fait dans un script SQL. Ce message apparaît juste en premier après la recherche.
jmosesman

Réponses:

428

Utilisez la méthode statique Guid.NewGuid()au lieu d'appeler le constructeur par défaut.

var responseObject = proxy.CallService(new RequestObject
{
    Data = "misc. data",
    Guid = Guid.NewGuid()
});
Mark Byers
la source
18
+1 pour la bonne réponse ainsi qu'un lien vers la documentation appropriée.
ObscureRobot
109

Leçons à en tirer:

1) Guid est un type de valeur, pas un type de référence.

2) L'appel du constructeur par défaut new S()sur n'importe quel type de valeur vous renvoie toujours la forme entièrement nulle de ce type de valeur, quelle qu'elle soit. C'est logiquement le même que default(S).

Eric Lippert
la source
3
Compile-t-il dans le même IL default(S)ou y a-t-il des subtilités qui me manquent?
configurateur
8
@configurator: Oui. En fait, la représentation interne du compilateur de "default (S)" et "new S ()" est la même; nous ne les distinguons pas en interne, ce qui a conduit à des bugs malheureux au fil des années car ils ne sont en fait pas tout à fait identiques. Par exemple, const int x = new int();n'est pas censé être légal selon la spécification, mais l' const int x = default(int);est; nous autorisons les deux.
Eric Lippert
1
@configurator - si vous êtes intéressé par les cas d'angle connexes, peut-être que msmvps.com/blogs/jon_skeet/archive/2008/12/10/… serait également intéressant.
kvb
56

Essayez plutôt ceci:

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

Cela générera une «vraie» valeur Guid. Lorsque vous créez un type de référence, il vous donnera la valeur par défaut (qui dans ce cas, est tous des zéros pour un Guid).

Lorsque vous créez un nouveau Guid, il l'initialise à tous les zéros, ce qui est la valeur par défaut de Guid. C'est fondamentalement la même chose que de créer un "nouveau" int (qui est un type de valeur mais vous pouvez le faire quand même):

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

Comparez cela à la même chose avec un int:

int i1;                     // i1 is 0
int i2 = new int();         // i2 is 0
int i3 = default(int);      // i3 is 0
JohnD
la source
1
g1compilera uniquement en tant que champ et non en tant que variable locale. De plus, les indices dans votre colonne de commentaires ne correspondent pas à la même ligne du code
CodesInChaos
1
@CodeInChaos: Merci, correction des commentaires. Pour info, la ligne g1 compile réellement ...
JohnD
3
Il se compilera tel quel, mais il n'a pas de valeur définie. Si vous ajoutez du code qui le lit (avant d'y écrire), il ne sera plus compilé.
CodesInChaos
1
Bon, bon point, vous obtiendrez une erreur si vous utilisez une variable non initialisée, donc la valeur ne peut pas être utilisée.
JohnD
1
voté contre parce que la ligne "Guid = Guid.NewGuid ();" peut confondre les nouveaux développeurs. Pensez à modifier quelque chose comme "Guid someGuid = Guid.NewGuid ();" comme la ligne g2;)
daviesdoesit
25

Essayez de faire:

Guid foo = Guid.NewGuid();
Dylan Smith
la source
1
Raison du downvote: "Guid" est un type mais est utilisé comme une variable.
daviesdoesit
19

Je ne peux pas vous dire combien de fois cela s'est produit. moi.

Guid myGuid = Guid.NewGuid(); 
Matt Dawdy
la source
11

Dans l'esprit d'être complet, les réponses qui vous demandent d'utiliser Guid.NewGuid()sont correctes.

Pour traiter votre modification ultérieure, vous devrez publier le code de votre RequestObjectclasse. Je soupçonne que votre propriété guid n'est pas marquée comme un DataMember, et n'est donc pas sérialisée sur le fil. Puisque default(Guid)c'est la même chose new Guid()(c'est-à-dire tous 0), cela expliquerait le comportement que vous voyez.

Adam Robinson
la source