Jan 31, 2024

Les structures en C# sont amusantes - Partie 6/9: Struct avec des valeurs d'argument par défaut dans les constructeurs, ou, n'êtes-vous pas encore confus ?

Leia este post em Português

Read this post in english

  1. Les structures en C# sont amusantes
  2. Brève introduction aux Value Types vs Reference Types.
  3. Initialisation des champs dans les structures.
  4. Comportement des constructeurs dans structures.
  5. Des autres scénarios dans lesquels le comportement des constructeurs de structure peut vous surprendre.
  6. Struct avec des valeurs d'argument par défaut dans les constructeurs, ou, n'êtes-vous pas encore confus ? (cet post)
  7. Le modificateur required de C # 11 ne sauvegardera pas votre c*l emploi.
  8. Structure utilisée comme valeurs d'argument défaut.
  9. Bonus: L'evolution des structures en C#.

Dans les derniere posts, nous avons vu que le compilateur C# peut net pas exécuter le constructeur des structs dans certains scénarios. Malheureusement, l'expérience avec les constructeurs dans les structures, du moins à mon avis, peut devenir encore plus déroutante.

Pour illustrer mon point, supposons que vous ayez le code suivant :

Print(new S2()); 
Print(new S2(13));

void Print(S2 s) => System.Console.WriteLine(s.v);

struct S2
{ 
    public int v;
    public S2(int i = 42)  => v = i;
    public S2() => v = 84;
}

Quel résultat attendez-vous s’il est compilé/exécuté1 ?

  1. Le compilateur émettra une erreur en affirmant que new S2() est un appel ambigu.
  2. Il compile et génère 42, 13.
  3. Il compile et génère 84, 13.

La bonne réponse, qui peut surprendre certains développeurs, est qu'il se compile avec succès et affiche 84 et 13 (c'est-à-dire la troisième option).

Cela se produit parce qu'à la ligne 1, le compilateur C# considère le constructeur sans paramètre comme une meilleure correspondance (better match) que celui avec la valeur de paramètre par défaut excluant les options 1 et 21. Le bon côté est que même si cela n'est pas totalement évident, au moins ce comportement est cohérent entre les classes/structures.

Pourtant, avec les structures, cela peut devenir encore plus complexe/déroutant ; imaginez que vous avez exactement le même code que ci-dessus, la seule différence étant la suppression du constructeur sans paramètre :

Print(new S2()); 
Print(new S2(13));

void Print(S2 s) => System.Console.WriteLine(s.v);

struct S2
{ 
    public int v;
    public S2(int i = 42)  => v = i;
}

maintenant, c'est sûr qu'il imprimera 42, 13, n'est-ce pas ?

Non! Dans ce scénario, contrairement aux classes, un constructeur avec des valeurs par défaut pour tous ses paramètres n'est pas invoqué, même sur une new expression explicite2, ce qui signifie que le code ci-dessus imprimera 0 et 133.

Dans le prochain article, nous examinerons rapidement les membres requis C# 114 comme moyen d'aider à identifier les scénarios dans lesquels aucun constructeur n'est invoqué.

Comme toujours, tous les commentaires sont les bienvenus.

Amusez-vous!


  1. Pour être honnête, le comportement ici est le même pour les classes, donc au moins il est cohérent.

  2. la spécification des constructeurs sans paramètre dans les structures indique explicitement que ce comportement est le même que dans les versions précédentes de C#.

  3. Cela se produit parce que la ligne n°1 est équivalente à Print(default(S2)) ; pour plus de détails, voir cet article.

  4. Je suis conscient que ce n'est pas l'utilisation prévue de cette fonctionnalité, mais elle peut être utilisée pour signaler quelques instanciations de structure qui n'invoquent pas de constructeur.

No comments: