Mehrere Fälle, in switch-Anweisung
-
09-06-2019 - |
Frage
Gibt es eine Möglichkeit durch mehrere case-Anweisungen zu fallen, ohne Angabe case value:
wiederholt?
Ich weiß, das funktioniert:
switch (value)
{
case 1:
case 2:
case 3:
//do some stuff
break;
case 4:
case 5:
case 6:
//do some different stuff
break;
default:
//default stuff
break;
}
, aber ich möchte so etwas tun:
switch (value)
{
case 1,2,3:
//Do Something
break;
case 4,5,6:
//Do Something
break;
default:
//Do the Default
break;
}
Ist diese Syntax ich von einer anderen Sprache denke, oder bin ich etwas fehlt?
Lösung
Es gibt keine Syntax in C ++ noch C # für die zweite Methode, die Sie erwähnt.
Es ist nichts falsch mit dem ersten Verfahren. Wenn Sie jedoch sehr große Bereiche haben, verwenden Sie nur eine Reihe von if-Anweisungen.
Andere Tipps
Ich denke, das bereits beantwortet wurde. Aber ich denke, dass Sie immer noch beide Möglichkeiten in einem syntaktisch besseren Weg mischen können, indem Sie:
switch (value)
{
case 1: case 2: case 3:
// Do Something
break;
case 4: case 5: case 6:
// Do Something
break;
default:
// Do Something
break;
}
Diese Syntax ist von dem Visual Basic wählen Sie ... Case-Anweisung :
Dim number As Integer = 8
Select Case number
Case 1 To 5
Debug.WriteLine("Between 1 and 5, inclusive")
' The following is the only Case clause that evaluates to True.
Case 6, 7, 8
Debug.WriteLine("Between 6 and 8, inclusive")
Case Is < 1
Debug.WriteLine("Equal to 9 or 10")
Case Else
Debug.WriteLine("Not between 1 and 10, inclusive")
End Select
Sie können diese Syntax in C # verwenden. Stattdessen müssen Sie die Syntax von Ihrem ersten Beispiel.
Ein bisschen spät für die ursprüngliche Frage, aber ich bin Entsendung diese Antwort in der Hoffnung, dass jemand eine neuere Version ( C # 7 verwenden - standardmäßig verfügbar in Visual Studio 2017 / .NET Framework 4.6.2 ), wird es hilfreich sein.
C # 7, bereichsbasierte Schalt ist nun möglich, mit der switch-Anweisung und würde sich mit dem Problem des OP helfen.
Beispiel:
int i = 5;
switch (i)
{
case int n when (n >= 7):
Console.WriteLine($"I am 7 or above: {n}");
break;
case int n when (n >= 4 && n <= 6 ):
Console.WriteLine($"I am between 4 and 6: {n}");
break;
case int n when (n <= 3):
Console.WriteLine($"I am 3 or less: {n}");
break;
}
// Output: I am between 4 and 6: 5
Weitere Informationen:
- Die Klammern
(
und)
sind nicht imwhen
Zustand erforderlich, werden aber in diesem Beispiel verwendet, um den Vergleich zu markieren (s). -
var
kann auch anstelle vonint
verwendet werden. Zum Beispiel:.case var n when n >= 7:
Sie können die Newline auslassen, die Sie gibt:
case 1: case 2: case 3:
break;
aber ich halte den schlechten Stil.
.NET Framework 3.5 hat bekommt Bereiche:
können Sie es mit „enthält“ verwenden und die IF-Anweisung, da wie jemand sagte die SWITCH-Anweisung den „==“ Operator verwendet.
Hier ein Beispiel:
int c = 2;
if(Enumerable.Range(0,10).Contains(c))
DoThing();
else if(Enumerable.Range(11,20).Contains(c))
DoAnotherThing();
Aber ich denke, wir können mehr Spaß haben: da Sie nicht die Rückgabewerte benötigen und diese Aktion Parameter nicht nehmen, können Sie leicht Aktionen verwenden
public static void MySwitchWithEnumerable(int switchcase, int startNumber, int endNumber, Action action)
{
if(Enumerable.Range(startNumber, endNumber).Contains(switchcase))
action();
}
Das alte Beispiel mit dieser neuen Methode:
MySwitchWithEnumerable(c, 0, 10, DoThing);
MySwitchWithEnumerable(c, 10, 20, DoAnotherThing);
Da Sie Aktionen sind vorbei, nicht Werte, sollten Sie die Klammern weglassen, es ist sehr wichtig. Wenn Sie Funktion mit Argumenten müssen, ändern Sie einfach die Art der Action
zu Action<ParameterType>
. Wenn Sie Werte benötigen zurückzukehren, verwenden Sie Func<ParameterType, ReturnType>
.
In C # 3.0 gibt es keine einfache Teil Anwendung die Tatsache das der Fall Parameter zu kapseln die gleiche, aber Sie ein kleines Hilfsmethode erstellen (ein bisschen ausführlicher, tho).
public static void MySwitchWithEnumerable(int startNumber, int endNumber, Action action){
MySwitchWithEnumerable(3, startNumber, endNumber, action);
}
Hier ist ein Beispiel dafür, wie neue funktionale importierte Aussage ist IMHO mächtiger und eleganter als die alte unbedingt ein.
@ Jennifer Owens: Sie sind absolut richtig der Code unten wird nicht funktionieren:
case 1 | 3 | 5:
//not working do something
Der einzige Weg, dies zu tun ist:
case 1: case 2: case 3:
// do something
break;
Der Code, den Sie für die Arbeiten auf Visual Basic suchen, wo man leicht Bereiche setzen können ... in keiner Möglichkeit, Schalter oder wenn sonst Blöcke bequem, würde ich vorschlagen, bei sehr extremen Punkt zu, DLL mit Visual Basic machen und importieren, um Ihre c # Projekt zurück.
. Hinweis: Schalter gleichwertig in Visual Basic wählen Fall
Eine andere Möglichkeit wäre eine Routine zu verwenden. Wenn alle Fälle 1-3 die gleiche Logik ausführen dann wickeln diese Logik in einer Routine, und nenne es für jeden Fall. Ich weiß, das eigentlich nicht bekommen die Beseitigung der Fall Aussagen, aber es funktioniert gut Stil umzusetzen und halten Wartung auf ein Minimum .....
[Bearbeiten] hinzugefügt alternative Implementierung ursprüngliche Frage passen ... [/ Edit]
switch (x)
{
case 1:
DoSomething();
break;
case 2:
DoSomething();
break;
case 3:
DoSomething();
break;
...
}
private void DoSomething()
{
...
}
Alt
switch (x)
{
case 1:
case 2:
case 3:
DoSomething();
break;
...
}
private void DoSomething()
{
...
}
Dies ist die komplette C # 7 Lösung ...
switch (value)
{
case var s when new[] { 1,2,3 }.Contains(s):
//Do Something
break;
case var s when new[] { 4,5,6 }.Contains(s):
//Do Something
break;
default:
//Do the Default
break;
}
Arbeiten mit Strings zu ...
switch (mystring)
{
case var s when new[] { "Alpha","Beta","Gamma" }.Contains(s):
//Do Something
break;
...
}
Eine weniger bekannte Facette von Schalter in C # ist, dass es stützt sich auf die operator = und da es Sie könnte so etwas wie diese haben werden außer Kraft gesetzt werden:
string s = foo();
switch (s) {
case "abc": /*...*/ break;
case "def": /*...*/ break;
}
gcc implementiert eine Erweiterung der Programmiersprache C Sequenzbereiche zu unterstützen:
switch (value)
{
case 1...3:
//Do Something
break;
case 4...6:
//Do Something
break;
default:
//Do the Default
break;
}
Bearbeiten :. Bemerkte einfach den C # Tag auf der Frage, so vermutlich eine gcc Antwort nicht helfen
Eigentlich mag ich nicht den Befehl GOTO auch, aber es ist in der offiziellen MS Materialien, hier sind Syntaxen alle erlaubt.
Wenn der Endpunkt der Anweisungsliste eines Schalterabschnittes erreichbar ist, ein Fehler bei der Kompilierung auftritt. Dies wird als „kein Fall durch“ -Regel bekannt. Das Beispiel
switch (i) {
case 0:
CaseZero();
break;
case 1:
CaseOne();
break;
default:
CaseOthers();
break;
}
ist gültig, weil kein Schaltabschnitt einen erreichbaren Endpunkt hat. Im Gegensatz zu C und C ++, die Ausführung eines Schaltabschnitts ist nicht auf den nächsten Schaltabschnitt zu „fallen durch“ erlaubt, und das Beispiel
switch (i) {
case 0:
CaseZero();
case 1:
CaseZeroOrOne();
default:
CaseAny();
}
führt zu einem Fehler bei der Kompilierung. Wenn die Ausführung eines Schaltabschnitt ist durch die Ausführung eines anderen Schaltabschnitt gefolgt werden kann, muss eine explizite goto Fall oder goto default-Anweisung verwendet werden:
switch (i) {
case 0:
CaseZero();
goto case 1;
case 1:
CaseZeroOrOne();
goto default;
default:
CaseAny();
break;
}
Mehrere Etiketten werden in einem Switch-Abschnitt erlaubt. Das Beispiel
switch (i) {
case 0:
CaseZero();
break;
case 1:
CaseOne();
break;
case 2:
default:
CaseTwo();
break;
}
ich in diesem speziellen Fall glauben, kann die GOTO verwendet werden, es ist tatsächlich der einzige Weg, um Durchfall.
Quelle: http: // msdn. microsoft.com/en-us/library/aa664749%28v=vs.71%29.aspx
Eine Menge Arbeit scheint in sein stellen Wege zu finden, einen von C # wenigsten verwendeten Syntaxen erhalten irgendwie besser aussehen oder besser funktionieren. Persönlich finde ich die Anweisung switch selten wert verwenden. Ich würde vorschlagen, stark zu analysieren, welche Daten Sie testen und das Ende Ergebnisse, die Sie wollen.
Nehmen wir zum Beispiel sagen, Sie wollen schnell testen, Werte in einem bekannten Bereich zu sehen, ob sie Primzahlen sind. Sie wollen Ihren Code tun, um die unnützen Berechnungen zu vermeiden, und Sie können eine Liste der Primzahlen im Bereich Sie wollen online finden. Sie könnten eine massive switch-Anweisung verwenden, um jeden Wert zu bekannte Primzahlen miteinander zu vergleichen.
Oder Sie könnten nur eine Reihe Karte von Primzahlen erstellen und sofort Ergebnisse:
bool[] Primes = new bool[] {
false, false, true, true, false, true, false,
true, false, false, false, true, false, true,
false,false,false,true,false,true,false};
private void button1_Click(object sender, EventArgs e) {
int Value = Convert.ToInt32(textBox1.Text);
if ((Value >= 0) && (Value < Primes.Length)) {
bool IsPrime = Primes[Value];
textBox2.Text = IsPrime.ToString();
}
}
Vielleicht möchten Sie sehen, ob ein Zeichen in einer Zeichenkette hexadezimal ist. Sie könnten einen ungly und etwas große switch-Anweisung verwenden.
Oder Sie könnten entweder reguläre Ausdrücke verwenden, um die Zeichen zu testen oder die IndexOf Funktion für die Zeichen in einer Reihe von bekannten hexadezimalen Buchstaben suchen:
private void textBox2_TextChanged(object sender, EventArgs e) {
try {
textBox1.Text = ("0123456789ABCDEFGabcdefg".IndexOf(textBox2.Text[0]) >= 0).ToString();
} catch {
}
}
Lassen Sie uns sagen, Sie eines von 3 verschiedenen Aktionen tun wollen auf einem Wert abhängig, dass der Bereich von 1 bis 24 sein wird, würde ich vorschlagen, eine Reihe von IF-Anweisungen. Und wenn die zu komplex worden (oder die Zahlen größer waren wie 5 verschiedene Aktionen auf einem Wert, abhängig im Bereich von 1 bis 90), dann eine ENUM verwenden, um die Aktionen zu definieren, und ein Array der Karte enums erstellen. Der Wert würde dann auf Index in das Array Karte verwendet werden und die Enum der Aktion Sie wollen. Verwenden Sie dann entweder einen kleinen Satz von IF-Anweisungen oder eine sehr einfache Switch-Anweisung des resultierenden Enum-Wert zu verarbeiten.
Auch das Schöne an einem Array Karte, die eine Reihe von Werten in die Tat umsetzt, ist, dass sie leicht durch Code geändert werden kann. Mit fest verdrahtetem Code, den Sie nicht so leicht können das Verhalten zur Laufzeit ändern, aber mit einer Reihe Karte ist es einfach.
Wenn Sie eine sehr große Menge an Schnur (oder jeden andere Art) Fall all das gleiche tun, empfahl ich die Verwendung einer String-Liste mit der string.Contains Eigenschaft kombiniert werden.
Wenn Sie also eine große switch-Anweisung haben etwa so:
switch (stringValue)
{
case "cat":
case "dog":
case "string3":
...
case "+1000 more string": //Too many string to write a case for all!
//Do something;
case "a lonely case"
//Do something else;
.
.
.
}
Vielleicht möchten Sie es mit einer if-Anweisung wie folgt ersetzt werden:
//Define all the similar "case" string in a List
List<string> listString = new List<string>(){ "cat", "dog", "string3", "+1000 more string"};
//Use string.Contains to find what you are looking for
if (listString.Contains(stringValue))
{
//Do something;
}
else
{
//Then go back to a switch statement inside the else for the remaining cases if you really need to
}
Diese Skala gut für eine beliebige Anzahl von String-Fall.
Dazu würden Sie eine goto-Anweisung verwenden. Wie zum Beispiel:
switch(value){
case 1:
goto case 3;
case 2:
goto case 3;
case 3:
DoCase123();
//This would work too, but I'm not sure if it's slower
case 4:
goto case 5;
case 5:
goto case 6;
case 6:
goto case 7;
case 7:
DoCase4567();
}