Wie muss ein Schalterausdruck geschrieben werden, um mehrere Fälle zu unterstützen, die dasselbe Ergebnis zurückgeben?
Mit c # vor Version 8 kann ein Schalter wie folgt geschrieben werden:
var switchValue = 3;
var resultText = string.Empty;
switch (switchValue)
{
case 1:
case 2:
case 3:
resultText = "one to three";
break;
case 4:
resultText = "four";
break;
case 5:
resultText = "five";
break;
default:
resultText = "unkown";
break;
}
Wenn ich die Ausdruckssyntax von c # Version 8 verwende, ist dies wie folgt:
var switchValue = 3;
var resultText = switchValue switch
{
1 => "one to three",
2 => "one to three",
3 => "one to three",
4 => "four",
5 => "five",
_ => "unknown",
};
Meine Frage lautet also: Wie werden die Fälle 1, 2 und 3 zu nur einem Schalter-Fall-Arm, damit der Wert nicht wiederholt werden muss?
Update per Vorschlag von " Rufus L ":
Für mein gegebenes Beispiel funktioniert dies.
var switchValue = 3;
var resultText = switchValue switch
{
var x when (x >= 1 && x <= 3) => "one to three",
4 => "four",
5 => "five",
_ => "unknown",
};
Aber es ist nicht genau das, was ich erreichen möchte. Dies ist immer noch nur ein Fall (mit einer Filterbedingung), nicht mehrere Fälle, die zum gleichen Ergebnis auf der rechten Seite führen.
c#
c#-8.0
switch-expression
Huzle
quelle
quelle
when
ist sowieso weitaus mächtiger als fall-through. Sie könnenContains
mit einem Array von Werten verwenden, wenn Sie möchten.var x when listOfValues.Contains(x)
case 1: case 2:
tun ist - es sind Fälle mit leeren Blöcken, die bis zum nächstenwhen
können weitaus komplexere Fälle behandeln als einfaches Durchfallen. Der einfache Durchfall kann nur Gleichheitsprüfungen gegen einen fest codierten Wert durchführen. Mustervergleich undwhen
sind in Schalterausdrücken gleich. Tatsächlich sind es switch- Anweisungen , die Probleme beim Pattern Matching verursachen. Wenn Sie funktionale Sprachen wie F # überprüfen, werden Sie feststellen, dass der primäre Anwendungsfall (häufig der einzige ) Mustervergleichsausdrücke sind.Antworten:
Ich habe es installiert, aber ich habe keine Möglichkeit gefunden, mehrere separate Fallbezeichnungen für einen einzelnen Switch-Abschnitt mit der neuen Syntax anzugeben.
Sie können jedoch eine neue Variable erstellen, die den Wert erfasst, und dann eine Bedingung verwenden, um die Fälle darzustellen, die dasselbe Ergebnis haben sollten:
var resultText = switchValue switch { var x when x == 1 || x == 2 || x == 3 => "one to three", 4 => "four", 5 => "five", _ => "unknown", };
Dies ist tatsächlich prägnanter, wenn Sie viele Fälle testen müssen, da Sie einen Wertebereich in einer Zeile testen können:
var resultText = switchValue switch { var x when x > 0 && x < 4 => "one to three", 4 => "four", 5 => "five", _ => "unknown", };
quelle
when
Klausel ist weitaus mächtiger als ohnehin durchzufallen. Anstatt 3 oder 10case
Aussagen zu schreiben , können Sie eine einzelne verwendenvar x when listOfValues.Contains(x)
Leider scheint dies ein Mangel in der Switch-Ausdruckssyntax im Vergleich zur Switch-Anweisungssyntax zu sein. Wie andere Poster vorgeschlagen haben, ist die eher ungeschickte
var
Syntax Ihre einzige echte Option.Sie hätten also gehofft, Sie könnten schreiben:
switchValue switch { Type1 t1: Type2 t2: Type3 t3 => ResultA, // where the ResultX variables are placeholders for expressions. Type4 t4 => ResultB, Type5 t5 => ResultC };
Stattdessen müssen Sie den ziemlich umständlichen Code unten mit dem gesprühten Typnamen schreiben:
switchValue switch { var x when x is Type1 || x is Type2 || x is Type 3 => ResultA, Type4 t4 => ResultB, Type5 t5 => ResultC };
In einem so einfachen Beispiel können Sie wahrscheinlich mit dieser Unbeholfenheit leben. Aber kompliziertere Beispiele sind viel weniger lebenswert. Tatsächlich sind meine Beispiele eine Vereinfachung eines Beispiels aus unserer eigenen Codebasis, in der ich gehofft hatte, eine switch-Anweisung mit ungefähr sechs Ergebnissen, aber über einem Dutzend Typfällen in einen switch-Ausdruck umzuwandeln. Und das Ergebnis war deutlich weniger lesbar als die switch-Anweisung.
Meiner Ansicht nach sollten Sie sich besser an eine switch-Anweisung halten, wenn der switch-Ausdruck gemeinsame Ergebnisse benötigt und mehr als ein paar Zeilen lang ist. Boo! Es ist ausführlicher, aber wahrscheinlich eine Freundlichkeit für Ihre Teamkollegen.
ResultType tmp; switch (switchValue) { case Type1 t1: case Type2 t2: case Type3 t3: tmp = ResultA; break; case Type4 t4: tmp = ResultB; break; case Type5 t5: tmp = ResultC; break; }; return tmp;
quelle
tmp
. Auf diese Weise können Sie auch dasbreak
s weglassen .case Type1 _:
,case Type2 _:
usw.C # 9 unterstützt Folgendes:
var switchValue = 3; var resultText = switchValue switch { 1 or 2 or 3 => "one, two, or three", 4 => "four", 5 => "five", _ => "unknown", };
Alternative:
var switchValue = 3; var resultText = switchValue switch { >= 1 and <= 3 => "one, two, or three", 4 => "four", 5 => "five", _ => "unknown", };
Quelle
Für ältere Versionen von C # verwende ich die folgende Erweiterungsmethode:
public static bool In<T>(this T val, params T[] vals) => vals.Contains(val);
so was:
var switchValue = 3; var resultText = switchValue switch { var x when x.In(1, 2, 3) => "one, two, or three", 4 => "four", 5 => "five", _ => "unknown", };
Es ist etwas prägnanter als
when x == 1 || x == 2 || x == 3
und hat eine natürlichere Reihenfolge alswhen new [] {1, 2, 3}.Contains(x)
.quelle
Wenn Ihr Switch-Typ eine Flag-Aufzählung ist
[System.Flags] public enum Values { One = 1, Two = 2, Three = 4, Four = 8, OneToThree = One | Two | Three } var resultText = switchValue switch { var x when Values.OneToThree.HasFlag(x) => "one to three", Values.Four => "4", _ => "unknown", };
quelle