C # 7: Underscore (_) & Star (*) dans la variable Out

Je lisais ici les nouvelles fonctionnalités variables de C # 7. J’ai deux questions:

  1. Ça dit

    Nous autorisons également les parameters “rejetés”, sous la forme d’un _ , pour vous permettre d’ignorer les parameters qui ne vous intéressent pas:

     p.GetCoordinates(out var x, out _); // I only care about x 

    Q: Je suppose que c’est juste une info et non une nouvelle fonctionnalité de C # 7 parce que nous pouvons le faire aussi dans pre C # 7.0:

     var _; if (Int.TryParse(str, out _)) ... 

    ou est-ce que je manque quelque chose ici?

  2. Mon code donne une erreur quand je le fais comme mentionné dans le même blog:

     ~Person() => names.TryRemove(id, out *); 

    * n’est pas un identifiant valide. Un oubli de Mads Torgersen, je suppose?

Les rejets, en C # 7, peuvent être utilisés partout où une variable est déclarée, pour supprimer – comme son nom l’indique – le résultat. Donc, il peut être utilisé avec des variables:

 p.GetCoordinates(out var x, out _); 

et il peut être utilisé pour écarter un résultat d’expression:

 _ = 42; 

Dans l’exemple,

 p.GetCoordinates(out var x, out _); _ = 42; 

Il n’y a pas de variable _ introduite. Il n’y a que deux cas de rejet utilisés.

Si toutefois, un identifiant _ existe dans la scope, alors les rejets ne peuvent pas être utilisés:

 var _ = 42; _ = "hello"; // error - a ssortingng cannot explicitly convert from ssortingng to int 

L’exception à cela est quand une variable _ est utilisée comme variable de sortie. Dans ce cas, le compilateur ignore le type ou var et le traite comme une suppression:

 if (p.GetCoordinates(out double x, out double _)) { _ = "hello"; // works fine. Console.WriteLine(_); // error: _ doesn't exist in this context. } 

Notez que cela ne se produit que si, dans ce cas, out var _ ou out double _ est utilisé. Il suffit d’utiliser out _ et il est traité comme une référence à une variable existante, _ si elle est dans la scope, par exemple:

 ssortingng _; int.TryParse("1", out _); // complains _ is of the wrong type 

Enfin, la notation * été proposée tôt dans les discussions sur les rejets, mais a été abandonnée au profit de _ car cette dernière est une notation plus couramment utilisée dans d’autres langues .

Pour plus curieux

Considérez l’extrait suivant

 static void Main(ssortingng[] args) { //.... int a; int b; Test(out a, out b); Test(out _, out _); //.... } private static void Test(out int a, out int b) { //... } 

C’est ce qui se passe:

 ... 13: int a; 14: int b; 15: 16: Test(out a, out b); 02340473 lea ecx,[ebp-40h] 02340476 lea edx,[ebp-44h] 02340479 call 02340040 0234047E nop 17: Test(out _, out _); 0234047F lea ecx,[ebp-48h] 02340482 lea edx,[ebp-4Ch] 02340485 call 02340040 0234048A nop ... 

Comme vous pouvez le voir derrière la scène, les deux appels font la même chose.

Comme @ Servé Laurijssen l’a souligné, ce qui est cool, c’est que vous n’avez pas à pré-déclarer de variables, ce qui est pratique si vous n’êtes pas intéressé par certaines valeurs.

Un autre exemple de l’opérateur Discard _ dans C # 7 est de mettre en correspondance une variable de type object dans une instruction switch , qui a été récemment ajoutée dans C # 7:

Code:

 static void Main(ssortingng[] args) { object x = 6.4; switch (x) { case ssortingng _: Console.WriteLine("it is ssortingng"); break; case double _: Console.WriteLine("it is double"); break; case int _: Console.WriteLine("it is int"); break; default: Console.WriteLine("it is Unknown type"); break; } // end of main method } 

Ce code correspond au type et ignore la variable transmise au case ... _ .

En ce qui concerne la première question

Je suppose que c’est juste une info et non une nouvelle fonctionnalité de C # 7 car nous pouvons le faire aussi dans le pré-C # 7.0.

 var _; if (Int.TryParse(str, out _)) // ... 

La nouveauté est que vous n’avez plus à déclarer _ intérieur ou à l’extérieur de l’expression et vous pouvez simplement taper

 int.TryParse(s, out _); 

Essayez de faire ce liner pre C # 7:

 private void btnDialogOk_Click_1(object sender, RoutedEventArgs e) { DialogResult = int.TryParse(Answer, out _); }