Is er een manier om door meerdere case-statements te bladeren zonder herhaaldelijk case value:
te vermelden?
Ik weet dat dit werkt:
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;
}
maar ik zou zoiets als dit willen doen:
switch (value)
{
case 1,2,3:
// Do something
break;
case 4,5,6:
// Do something
break;
default:
// Do the Default
break;
}
Is deze syntaxis waar ik aan denk uit een andere taal, of mis ik iets?
Antwoord 1, autoriteit 100%
Er is geen syntaxis in C++ of C# voor de tweede methode die u noemde.
Er is niets mis met je eerste methode. Als je echter zeer grote bereiken hebt, gebruik dan gewoon een reeks if-statements.
Antwoord 2, autoriteit 95%
Volgens mij is dit al beantwoord. Ik denk echter dat je beide opties nog steeds syntactisch beter kunt combineren door:
switch (value)
{
case 1: case 2: case 3:
// Do Something
break;
case 4: case 5: case 6:
// Do Something
break;
default:
// Do Something
break;
}
Antwoord 3, autoriteit 26%
In C # 7 (standaard beschikbaar in Visual Studio 2017 / .NET Framework 4.6.2), bereikgerichte schakeling is nu mogelijk met de Schakel statement en zou helpen met het probleem van de OP.
Voorbeeld:
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
Opmerkingen:
- De haakjes
(
en)
zijn niet vereist in dewhen
Conditie, maar in dit voorbeeld worden gebruikt om de vergelijking (en) te markeren . var
kan ook worden gebruikt in plaats vanint
. Bijvoorbeeld:case var n when n >= 7:
.
4, Autoriteit 21%
Deze syntaxis is van de visuele basis Selecteer … Case-statement :
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
U kunt deze syntaxis niet gebruiken in C#. In plaats daarvan moet je de syntaxis van je eerste voorbeeld gebruiken.
Antwoord 5, autoriteit 10%
Je kunt de nieuwe regel weglaten die je het volgende geeft:
case 1: case 2: case 3:
break;
maar dat vind ik een slechte stijl.
Antwoord 6, autoriteit 6%
.NET Framework 3.5 heeft bereiken:
je kunt het gebruiken met “bevat” en de IF-instructie, aangezien zoals iemand zei, de SWITCH-instructie de “==” operator gebruikt.
Hier een voorbeeld:
int c = 2;
if(Enumerable.Range(0,10).Contains(c))
DoThing();
else if(Enumerable.Range(11,20).Contains(c))
DoAnotherThing();
Maar ik denk dat we meer plezier kunnen hebben: aangezien je de retourwaarden niet nodig hebt en deze actie geen parameters vereist, kun je gemakkelijk acties gebruiken!
public static void MySwitchWithEnumerable(int switchcase, int startNumber, int endNumber, Action action)
{
if(Enumerable.Range(startNumber, endNumber).Contains(switchcase))
action();
}
Het oude voorbeeld met deze nieuwe methode:
MySwitchWithEnumerable(c, 0, 10, DoThing);
MySwitchWithEnumerable(c, 10, 20, DoAnotherThing);
Omdat je acties en geen waarden doorgeeft, moet je de haakjes weglaten, dit is erg belangrijk. Als je een functie met argumenten nodig hebt, verander dan gewoon het type Action
in Action<ParameterType>
. Als u retourwaarden nodig heeft, gebruikt u Func<ParameterType, ReturnType>
.
In C# 3.0 is er geen gemakkelijke Gedeeltelijke toepassingom het feit dat de parameter case is hetzelfde, maar je maakt een kleine hulpmethode (een beetje uitgebreid, dat wel).
public static void MySwitchWithEnumerable(int startNumber, int endNumber, Action action){
MySwitchWithEnumerable(3, startNumber, endNumber, action);
}
Hier een voorbeeld van hoe een nieuwe functionele geïmporteerde verklaring IMHO krachtiger en eleganter is dan de oude imperatief.
Antwoord 7, autoriteit 5%
Hier is de complete C# 7-oplossing…
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;
}
Het werkt ook met strings…
switch (mystring)
{
case var s when new[] { "Alpha","Beta","Gamma" }.Contains(s):
// Do something
break;
...
}
Antwoord 8, autoriteit 4%
De onderstaande code werkt niet:
case 1 | 3 | 5:
// Not working do something
De enige manier om dit te doen is:
case 1: case 2: case 3:
// Do something
break;
De code die u zoekt werkt in Visual Basic, waar u gemakkelijk bereiken kunt plaatsen… in de optie none
van de switch
-instructie of if else
blokkeert handig, raad ik aan om op een zeer extreem punt .dll te maken met Visual Basic en terug te importeren naar uw C#-project.
Opmerking: het switch-equivalent in Visual Basic is Select Case
.
Antwoord 9, autoriteit 2%
Met C#9 kwam de Relational Pattern Matching. Dit stelt ons in staat om het volgende te doen:
switch (value)
{
case 1 or 2 or 3:
// Do stuff
break;
case 4 or 5 or 6:
// Do stuff
break;
default:
// Do stuff
break;
}
In diepgaande tutorial van Relational Patter in C# 9
Patroonovereenkomstige wijzigingen voor C# 9.0
Relationele patronen stellen de programmeur in staat om die input uit te drukken
waarde moet voldoen aan een relationele beperking in vergelijking met een constante
waarde
Antwoord 10, autoriteit 2%
Een andere optie zou zijn om een routine te gebruiken. Als gevallen 1-3 allemaal dezelfde logica uitvoeren, wikkel die logica dan in een routine en roep het voor elk geval aan. Ik weet dat dit niet echt van de case-statements afkomt, maar het implementeert wel een goede stijl en beperkt het onderhoud tot een minimum…..
[Bewerken] Alternatieve implementatie toegevoegd die overeenkomt met de oorspronkelijke vraag…[/Bewerken]
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()
{
...
}
11
Een minder bekende facet van Switch in C # is dat het op de -operator = vertrouwt en omdat het kan worden ingrijpt, zou u zoiets kunnen hebben:
string s = foo();
switch (s) {
case "abc": /*...*/ break;
case "def": /*...*/ break;
}
12
GCC implementeert een uitbreiding van de C-taal om opeenvolgende reeksen te ondersteunen:
switch (value)
{
case 1...3:
//Do Something
break;
case 4...6:
//Do Something
break;
default:
//Do the Default
break;
}
Bewerken b>: Net opmerkte de C # -tag op de vraag, dus vermoedelijk helpt een GCC-antwoord niet.
13
Eigenlijk vind ik het Goto-commando ook niet leuk, maar het is in officiële Microsoft-materialen, en hier zijn allemaal toegestane syntaxis.
Als het eindpunt van de instructielijst van een switch-sectie bereikbaar is, treedt er een compileer-tijdfout op. Dit staat bekend als de “No Fall Through” -regel. Het voorbeeld
switch (i) {
case 0:
CaseZero();
break;
case 1:
CaseOne();
break;
default:
CaseOthers();
break;
}
is geldig omdat er geen sectie-sectie een bereikbaar eindpunt heeft. In tegenstelling tot C en C++ is de uitvoering van een switch-sectie niet toegestaan om “door te vallen” naar de sectie Volgende schakelaar, en het voorbeeld
switch (i) {
case 0:
CaseZero();
case 1:
CaseZeroOrOne();
default:
CaseAny();
}
resulteert in een compilertijdfout. Wanneer de uitvoering van een switch-sectie moet worden gevolgd door uitvoering van een ander schakelaargedeelte, moet een expliciete GOTO- of GOTO-standaardverklaring worden gebruikt:
switch (i) {
case 0:
CaseZero();
goto case 1;
case 1:
CaseZeroOrOne();
goto default;
default:
CaseAny();
break;
}
Meerdere labels zijn toegestaan in een schakelgedeelte. Het voorbeeld
switch (i) {
case 0:
CaseZero();
break;
case 1:
CaseOne();
break;
case 2:
default:
CaseTwo();
break;
}
Ik geloof dat in dit specifieke geval de GOTO kan worden gebruikt, en het is eigenlijk de enige manier om er doorheen te komen.
Antwoord 14
In C# 8.0 kun je de nieuwe van expressie wisselensyntaxis die ideaal is voor uw geval.
var someOutput = value switch
{
>= 1 and <= 3 => <Do some stuff>,
>= 4 and <= 6 => <Do some different stuff>,
_ => <Default stuff>
};
Antwoord 15
Er lijkt ontzettend veel werk te zijn gestoken in het vinden van manieren om een van de minst gebruikte syntaxis van C# er op de een of andere manier beter uit te laten zien of beter te laten werken. Persoonlijk vind ik de switch-statement zelden de moeite waard om te gebruiken. Ik raad je ten zeerste aan om te analyseren welke gegevens je aan het testen bent en welke eindresultaten je wilt.
Stel bijvoorbeeld dat u snel waarden in een bekend bereik wilt testen om te zien of het priemgetallen zijn. U wilt voorkomen dat uw code de verspillende berekeningen doet en u kunt online een lijst met priemgetallen vinden in het bereik dat u wilt. Je zou een massieve switch-instructie kunnen gebruiken om elke waarde te vergelijken met bekende priemgetallen.
Of u kunt gewoon een matrixkaart van priemgetallen maken en onmiddellijk resultaat krijgen:
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();
}
}
Misschien wil je zien of een teken in een string hexadecimaal is. Je zou een lelijke en ietwat grote switch-statement kunnen gebruiken.
Of je kunt ofwel reguliere expressies gebruiken om de char te testen of de IndexOf-functie gebruiken om naar de char te zoeken in een reeks bekende hexadecimale letters:
private void textBox2_TextChanged(object sender, EventArgs e) {
try {
textBox1.Text = ("0123456789ABCDEFGabcdefg".IndexOf(textBox2.Text[0]) >= 0).ToString();
} catch {
}
}
Stel dat je een van de 3 verschillende acties wilt uitvoeren, afhankelijk van een waarde die in het bereik van 1 tot 24 ligt. Ik raad je aan een set IF-instructies te gebruiken. En als dat te complex werd (of de getallen waren groter, zoals 5 verschillende acties, afhankelijk van een waarde in het bereik van 1 tot 90), gebruik dan een opsomming om de acties te definiëren en een matrixkaart van de opsommingen te maken. De waarde zou dan worden gebruikt om te indexeren in de matrixkaart en de opsomming te krijgen van de gewenste actie. Gebruik dan ofwel een kleine set IF-statements of een heel eenvoudig switch-statement om de resulterende opsommingswaarde te verwerken.
Het leuke van een matrixkaart die een reeks waarden in acties omzet, is dat deze eenvoudig door code kan worden gewijzigd. Met vast bedrade code kun je het gedrag tijdens runtime niet gemakkelijk veranderen, maar met een array-kaart is het gemakkelijk.
Antwoord 16
Als je een heel groot aantal strings (of een ander type) hebt die allemaal hetzelfde doen, raad ik het gebruik van een stringlijst aan in combinatie met de eigenschap string.Contains.
Dus als je een grote switch-statement hebt, zoals:
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;
.
.
.
}
Misschien wilt u het vervangen door een if
-statement zoals dit:
// 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
}
Deze schaal goed voor een willekeurig aantal tekenreeksen.
Antwoord 17
Ik denk dat deze beter is in C# 7 of hoger.
switch (value)
{
case var s when new[] { 1,2 }.Contains(s):
// Do something
break;
default:
// Do the default
break;
}
Je kunt het bereik ook controleren in de C#-switch: Switch case: kan ik een bereik gebruiken in plaats van een één nummer
Of als u de basis van
C#-switchcase
Antwoord 18
Om toe te voegen aan het gesprek, met .NET 4.6.2 kon ik ook het volgende doen.
Ik heb de code getest en het werkte voor mij.
U kunt ook meerdere “OF”-instructies doen, zoals hieronder:
switch (value)
{
case string a when a.Contains("text1"):
// Do Something
break;
case string b when b.Contains("text3") || b.Contains("text4") || b.Contains("text5"):
// Do Something else
break;
default:
// Or do this by default
break;
}
Je kunt ook controleren of het overeenkomt met een waarde in een array:
string[] statuses = { "text3", "text4", "text5"};
switch (value)
{
case string a when a.Contains("text1"):
// Do Something
break;
case string b when statuses.Contains(value):
// Do Something else
break;
default:
// Or do this by default
break;
}
Antwoord 19
U kunt ook voorwaarden hebben die totaal anders zijn
bool isTrue = true;
switch (isTrue)
{
case bool ifTrue when (ex.Message.Contains("not found")):
case bool ifTrue when (thing.number = 123):
case bool ifTrue when (thing.othernumber != 456):
response.respCode = 5010;
break;
case bool ifTrue when (otherthing.text = "something else"):
response.respCode = 5020;
break;
default:
response.respCode = 5000;
break;
}
Antwoord 20
Hiervoor zou je een goto-statement gebruiken. Zoals:
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();
}