Ich lese über neue aus variablen Funktionen in C # 7 hier . Ich habe zwei Fragen:
Es sagt
Wir erlauben auch "Verwerfen" als Out-Parameter in Form von a
_
, damit Sie Parameter ignorieren können, die Sie nicht interessieren:p.GetCoordinates(out var x, out _); // I only care about x
F: Ich denke, dies ist nur eine Information und keine neue Funktion von C # 7, da wir dies auch in Pre C # 7.0 tun können:
var _; if (Int.TryParse(str, out _)) ...
oder fehlt mir hier etwas
Mein Code gibt einen Fehler aus, wenn ich wie im selben Blog erwähnt vorgehe:
~Person() => names.TryRemove(id, out *);
*
ist keine gültige Kennung. Ein Versehen von Mads Torgersen, denke ich?
out _
_
ist keine Variable, Sie deklarieren sie nicht und können sie nicht mit Namen verwenden. Darinint _
liegt eine Variable.out _
, ohnevar
. Mit istvar
es in der Tat das gleiche wie zuvor.Console.WriteLine(_)
wird dies nicht kompiliert und behauptet, dass es keine solche Variable gibt. Ziemlich seltsam. Noch mehr: Wenn Sie so etwas tun,_ = SomeMethodCall()
wird dies durch nurSomeMethodCall()
kompilierten Code ersetzt. Schließlich können Sie diese Variable immer noch nicht wirklich in einem sinnvollen Sinne verwenden.Antworten:
Discards in C # 7 können überall dort verwendet werden, wo eine Variable deklariert ist, um - wie der Name schon sagt - das Ergebnis zu verwerfen. Ein Discard kann also ohne Variablen verwendet werden:
p.GetCoordinates(out var x, out _);
und es kann verwendet werden, um ein Ausdrucksergebnis zu verwerfen:
_ = 42;
Im Beispiel
p.GetCoordinates(out var x, out _); _ = 42;
Es wird keine Variable
_
eingeführt. Es gibt nur zwei Fälle, in denen ein Abwurf verwendet wird.Wenn jedoch ein Bezeichner
_
im Bereich vorhanden ist, können Rückwürfe nicht verwendet werden:var _ = 42; _ = "hello"; // error - a string cannot explicitly convert from string to int
Die Ausnahme ist, wenn eine
_
Variable als Out-Variable verwendet wird. In diesem Fall ignoriert der Compiler den Typ odervar
und behandelt ihn als Verwerfen:if (p.GetCoordinates(out double x, out double _)) { _ = "hello"; // works fine. Console.WriteLine(_); // error: _ doesn't exist in this context. }
Beachten Sie, dass dies nur auftritt, wenn in diesem Fall
out var _
oderout double _
verwendet wird. Verwendenout _
Sie einfach und dann wird es als Referenz auf eine vorhandene Variable behandelt_
, wenn es im Geltungsbereich liegt, z.string _; int.TryParse("1", out _); // complains _ is of the wrong type
Schließlich wurde die
*
Notation zu Beginn der Diskussionen um Rückwürfe vorgeschlagen, jedoch zugunsten der_
Notation aufgegeben , da letztere in anderen Sprachen häufiger verwendet wird .quelle
_
weil letzteres ein ...' ist_ = 42
"das Ausdrucksergebnis verwerfen" ist irreführend, da_ = 42
es sich selbst um einen Ausdruck mit dem Wert handelt42
, sodass kein tatsächliches Verwerfen stattfindet. Es gibt immer noch einen Unterschied, weil_ = 42;
es sich auch um eine Aussage handelt, während42;
dies in einigen Kontexten nicht der Fall ist._ = 42
nicht, wozu dieses Verwerfen dient - dh wenn Sie einen Ausdruck "nicht speichern", sondern trotzdem bewerten müssten, da Sie normalerweise einen (nicht trivialen) bewerten können , nützlicher) Ausdruck ganz gut, ohne ihn zu speichern. Ich kann mir nicht sofort ein nützliches Beispiel vorstellen (und ich weiß nicht, ob es eines gibt oder ob dies nur ein Ergebnis der Konsistenz in der Grammatik ist).Ein weiteres Beispiel des Discard Operators
_
in C # 7 ist auf Mustererkennung eine Variable vom Typobject
in einerswitch
Erklärung, die vor kurzem in C # 7 hinzugefügt wurde:Code:
static void Main(string[] args) { object x = 6.4; switch (x) { case string _: Console.WriteLine("it is string"); 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 }
Dieser Code entspricht dem Typ und verwirft die an die übergebene Variable
case ... _
.quelle
Für neugierigere
Betrachten Sie das folgende Snippet
static void Main(string[] args) { //.... int a; int b; Test(out a, out b); Test(out _, out _); //.... } private static void Test(out int a, out int b) { //... }
Folgendes passiert:
... 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 ...
Wie Sie hinter den Kulissen sehen können, machen die beiden Anrufe dasselbe.
Als @ Servé Laurijssen die kühle Sache wies darauf hin, dass Sie müssen nicht im Voraus declare Variablen , die praktisch ist , wenn Sie nicht in einigen Werten interessiert sind.
quelle
Zur ersten Frage
Das Neue ist, dass Sie nicht
_
mehr innerhalb oder außerhalb des Ausdrucks deklarieren müssen und einfach tippen könnenint.TryParse(s, out _);
Versuchen Sie, diesen einen Liner vor C # 7 zu machen:
private void btnDialogOk_Click_1(object sender, RoutedEventArgs e) { DialogResult = int.TryParse(Answer, out _); }
quelle
SomeMethod(out _, out _, out three)
mit 3 Out-Parametern, aber ich werfe die ersten beiden weg, ohne Variablen wieunused1, unused2
usw. erstellen zu müssen .if (SomeMethod(out _, out _, out _)) _ = 5;
Worauf_
bezieht es sich?_
Variable geben, selbst wenn Sie verwenden würdenout var _
. Es scheint, dass der Unterstrich ein spezielles Gehäuse ist, um das Ergebnis wegzuwerfen.In C # 7.0 (Visual Studio 2017 um März 2017) werden Verwerfungen in Zuweisungen in den folgenden Kontexten unterstützt:
Andere nützliche Hinweise
Einfaches Beispiel: Hier wollen wir nicht den 1. und 2. Parameter verwenden und brauchen nur den 3. Parameter
Erweitertes Beispiel im Switch-Fall, bei dem auch der moderne Switch-Case-Pattern-Matching ( Quelle ) verwendet wurde.
switch (exception) { case ExceptionCustom exceptionCustom: //do something unique //... break; case OperationCanceledException _: //do something else here and we can also cast it //... break; default: logger?.Error(exception.Message, exception); //.. break;
}}
quelle
var _; if (Int.TryParse(str, out _))
Das ist nicht dasselbe.
Ihr Code nimmt eine Zuordnung vor.
In C # 7.0 ist _ keine Variable, sondern weist den Compiler an, den Wert zu verwerfen
(es sei denn, Sie haben _ als Variable deklariert ... wenn Sie dies tun, wird die Variable anstelle des Verwerfungssymbols verwendet).
Beispiel: Sie können _ als Sting und Int in derselben Codezeile verwenden :
string a; int b; Test(out a, out b); Test(out _, out _); //... void Test(out string a, out int b) { //... }
quelle