Disons que j'ai une structure
public struct Foo
{
...
}
Y a-t-il une différence entre
Foo foo = new Foo();
et
Foo foo = default(Foo);
?
Disons que j'ai une structure
public struct Foo
{
...
}
Y a-t-il une différence entre
Foo foo = new Foo();
et
Foo foo = default(Foo);
?
Vous pouvez vous demander pourquoi, s'ils sont exactement les mêmes, il y a deux façons de faire la même chose.
Ils ne sont pas tout à fait les mêmes car chaque type de référence ou type de valeur est garanti avoir une valeur par défaut. mais il n'est pas garanti que tous les types de référence aient un constructeur sans paramètre :
static T MakeDefault<T>()
{
return default(T); // legal
// return new T(); // illegal
}
Non, les deux expressions donneront exactement le même résultat.
Puisque les structures ne peuvent pas contenir de constructeurs explicites sans paramètres (c'est-à-dire que vous ne pouvez pas en définir un vous-même), le constructeur par défaut vous donnera une version de la structure avec toutes les valeurs mises à zéro. C'est le même comportement que default
vous donne également.
Pour les types de valeurs, les options sont les suivantes, pratiquement parlant, équivalent.
Cependant, j'ai été intrigué par le livre de Jon Skeet. recherche empirique dans lesquelles les "instructions" aboutissent à l'invocation du constructeur par défaut sans paramètre d'une structure lorsqu'il est spécifié en CIL (vous ne pouvez pas le faire en C# car il ne vous le permet pas). Entre autres choses, il a testé default(T)
et new T()
où T
est un paramètre de type. Ils semblaient équivalents ; aucun d'entre eux ne semblait appeler le constructeur.
Mais le seul cas (apparemment) qu'il n'a pas essayé est le suivant. default(Foo)
où Foo
est un type de type de structure.
J'ai donc pris son code pour la structure "hackée" et je l'ai essayé moi-même.
Il s'avère que default(Foo) n'appelle pas le constructeur, alors que new Foo() le fait.
Utilisation d'un type struct Oddity
qui spécifie un constructeur sans paramètre :
Avec les optimisations désactivées la méthode :
private void CallDefault()
{
Oddity a = default(Oddity);
}
produit le CIL (sans nop
s, ret
etc.) :
L_0001: ldloca.s a
L_0003: initobj [Oddity]Oddity
alors que la méthode :
private void CallNew()
{
Oddity b = new Oddity();
}
produit :
L_0001: ldloca.s b
L_0003: call instance void [Oddity]Oddity::.ctor()
Avec les optimisations activées le compilateur semble optimiser à peu près tout ce qu'il faut. tous de la CallDefault
en un no-op, mais garde l'appel au constructeur dans CallNew
(pour les effets secondaires potentiels ?).
La spécification du langage (§4.1.2 et §5.2) est votre amie. Plus précisément :
Pour une variable d'un type de valeur la valeur par défaut est la même que la valeur calculée par la fonction type de valeur Le constructeur par défaut de l'utilisateur (§4.1.2).
(Italiques dans l'original.)
Notez qu'il n'en va pas de même pour les types de référence.
Pour une variable de type référence, la valeur par défaut est
null
.
C'est très différent de la valeur produite par un constructeur par défaut, s'il en existe un.
default
Le mot-clé est utile lorsque vous ne connaissez pas le type exact et il ne fonctionne pas seulement pour les structures, par exemple dans les génériques :
T FirstOrDefault(IEnumerable<T> source)
{
if (...source is empty...) return default(T);
}
Ceci retournera null pour les types de référence, la valeur par défaut pour les types primitifs (0 pour les nombres, false pour les bools), les structures inializées par défaut, etc ...
Lorsque le type est connu au moment de la compilation, il est inutile d'utiliser default
vous pouvez utiliser new Foo()
au lieu de
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.