272 votes

Guid est tous les 0 (zéros) ?

Je teste des services WCF qui envoient des objets avec des Guids dans les deux sens. Dans le code de test de mon 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 à nouveau Guid() génère des guides avec tous les 0 (zéros) comme ceci :

00000000-0000-0000-0000-000000000000

Quelle pourrait en être la cause ?

1 votes

132 votes

+1 parce que j'ai utilisé cette question pour voler un guide vierge une douzaine de fois :)

468voto

Mark Byers Points 318575

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()
});

21 votes

+1 pour la bonne réponse ainsi qu'un lien vers la documentation appropriée.

115voto

Eric Lippert Points 300275

Les leçons à tirer de cette affaire :

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

2) Appeler le constructeur par défaut new S() sur un type de valeur quelconque vous renvoie toujours la forme tout-zéro de ce type de valeur, quel qu'il soit. C'est logiquement la même chose que default(S) .

3 votes

Compile-t-il dans le même IL que default(S) ou y a-t-il des subtilités que je manque ?

8 votes

@configurateur : C'est le cas. En fait, la représentation interne du compilateur de "default(S)" et de "new S()" est la même ; nous ne les distinguons pas en interne, ce qui a conduit à quelques bugs malheureux au fil des ans parce qu'ils ne sont en fait pas tout à fait identique. Par exemple, const int x = new int(); n'est pas supposé être légal selon la spécification, mais const int x = default(int); est ; nous autorisons les deux.

1 votes

@configurator - si vous êtes intéressés par des cas particuliers, peut-être msmvps.com/blogs/jon_skeet/archive/2008/12/10/ serait également intéressante.

57voto

JohnD Points 6811

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 nouveau type de référence, il vous donnera la valeur par défaut (qui, dans ce cas, est constituée de tous les zéros pour un Guid).

Lorsque vous créez un nouveau Guid, il sera initialisé à tous les zéros, ce qui est la valeur par défaut pour 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 de toute façon) :

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 au fait de faire 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

1 votes

g1 ne sera compilé que comme champ et non comme variable locale. De plus, les indices dans votre colonne de commentaires ne correspondent pas à la même ligne de code.

1 votes

@CodeInChaos : Merci, j'ai corrigé les commentaires. Pour info, la ligne g1 compile effectivement...

3 votes

Il sera compilé 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 compilera plus.

26voto

Dylan Smith Points 11848

Essayez de le faire :

Guid foo = Guid.NewGuid();

1 votes

Raison du downvote : "Guid" est un type mais est utilisé comme une variable.

19voto

Matt Dawdy Points 5479

Je ne peux pas vous dire combien de fois ça m'a pris.

Guid myGuid = Guid.NewGuid();

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X