Несколько случаев в выражении switch - PullRequest
522 голосов
/ 16 сентября 2008

Есть ли способ пролистать несколько регистров без повторного ввода case value:?

Я знаю, что это работает:

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;
}

но я бы хотел сделать что-то вроде этого:

switch (value)
{
   case 1,2,3:
      //Do Something
      break;
   case 4,5,6:
      //Do Something
      break;
   default:
      //Do the Default
      break;
}

Это синтаксис, о котором я думаю из другого языка, или я что-то упустил?

Ответы [ 15 ]

642 голосов
/ 01 августа 2010

Полагаю, на это уже ответили. Тем не менее, я думаю, что вы все еще можете смешать оба варианта синтаксически лучше, выполнив:

switch (value)
{
case 1: case 2: case 3:          
    // Do Something
    break;
case 4: case 5: case 6: 
    // Do Something
    break;
default:
    // Do Something
    break;
}
285 голосов
/ 16 сентября 2008

Нет ни синтаксиса ни в C ++, ни в C # для второго упомянутого вами метода.

Нет ничего плохого в вашем первом методе. Однако, если у вас очень большие диапазоны, просто используйте серию операторов if.

68 голосов
/ 16 сентября 2008

Этот синтаксис взят из Visual Basic Выбрать ... Заявление о регистре :

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

Вы не можете использовать этот синтаксис в C #. Вместо этого вы должны использовать синтаксис из вашего первого примера.

47 голосов
/ 30 июня 2017

Немного опоздал на исходный вопрос, но я публикую этот ответ в надежде, что кто-то использует более новую версию ( C # 7 - по умолчанию доступна в Visual Studio 2017 / .NET Framework 4.6.2 ), сочтет это полезным.

В C # 7 переключение на основе диапазона теперь возможно с помощью оператора switch и поможет решить проблему OP.

Пример:

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

Примечания:

  • Скобки ( и ) не обязательны в условии when, но используются в этом примере, чтобы выделить сравнение (я).
  • var также может использоваться вместо int. Например: case var n when n >= 7:.
31 голосов
/ 16 сентября 2008

Вы можете пропустить символ новой строки, который дает вам:

case 1: case 2: case 3:
   break;

но я считаю этот плохой стиль.

18 голосов
/ 16 сентября 2008

.NET Framework 3.5 имеет диапазоны:

Enumerable.Range от MSDN

вы можете использовать его с «Содержит» и оператором IF, так как, как кто-то сказал, оператор SWITCH использует оператор «==».

Вот пример:

int c = 2;
if(Enumerable.Range(0,10).Contains(c))
    DoThing();
else if(Enumerable.Range(11,20).Contains(c))
    DoAnotherThing();

Но я думаю, что мы можем повеселиться: поскольку вам не понадобятся возвращаемые значения, а это действие не принимает параметров, вы можете легко использовать действия!

public static void MySwitchWithEnumerable(int switchcase, int startNumber, int endNumber, Action action)
{
    if(Enumerable.Range(startNumber, endNumber).Contains(switchcase))
        action();
}

Старый пример с этим новым методом:

MySwitchWithEnumerable(c, 0, 10, DoThing);
MySwitchWithEnumerable(c, 10, 20, DoAnotherThing);

Поскольку вы передаете действия, а не значения, вы должны опустить скобки, это очень важно. Если вам нужна функция с аргументами, просто измените тип Action на Action<ParameterType>. Если вам нужны возвращаемые значения, используйте Func<ParameterType, ReturnType>.

В C # 3.0 нет простого Частичного приложения для инкапсуляции того факта, что параметр case такой же, но вы создаете небольшой вспомогательный метод (немного многословный, хотя).

public static void MySwitchWithEnumerable(int startNumber, int endNumber, Action action){ 
    MySwitchWithEnumerable(3, startNumber, endNumber, action); 
}

Вот пример того, как новые функциональные импортированные операторы ИМХО более мощные и элегантные, чем старые императивные.

8 голосов
/ 04 ноября 2012

@ Дженнифер Оуэнс: вы абсолютно правы, приведенный ниже код не сработает:

case 1 | 3 | 5:
//not working do something

Единственный способ сделать это:

case 1: case 2: case 3:
// do something
break;

Код, который вы ищете, работает на Visual Basic, где вы легко можете поместить диапазоны ... без опции переключателя или, если это удобно, я бы посоветовал сделать в очень экстремальной точке .dll с Visual Basic и импортируйте обратно в ваш c # проект.

Примечание. Эквивалент переключателя в Visual Basic - это выбор.

7 голосов
/ 16 сентября 2008

Другим вариантом будет использование рутины. Если все случаи 1-3 выполняют одну и ту же логику, оберните эту логику в процедуру и вызовите ее для каждого случая. Я знаю, что на самом деле это не избавляет от инструкций case, но реализует хороший стиль и сводит обслуживание к минимуму .....

[Edit] Добавлена ​​альтернативная реализация для соответствия оригинальному вопросу ... [/ 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()
{
   ...
}
6 голосов
/ 28 декабря 2018

Вот полное решение C # 7 ...

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;
}

Работает и со строками ...

switch (mystring)
{
   case var s when new[] { "Alpha","Beta","Gamma" }.Contains(s):
      //Do Something
      break;
...
}
5 голосов
/ 16 сентября 2008

gcc реализует расширение языка C для поддержки последовательных диапазонов:

switch (value)
{
   case 1...3:
      //Do Something
      break;
   case 4...6:
      //Do Something
      break;
   default:
      //Do the Default
      break;
}

Редактировать : только что заметил тег C # в вопросе, поэтому, вероятно, ответ gcc не поможет.

...