Случай переключения: могу ли я использовать диапазон вместо одного числа


86

Я хочу использовать переключатель, но у меня много случаев, есть ли ярлык? Пока единственное решение, которое я знаю и пробовал:

switch (number)
{
case 1: something; break;
case 2: other thing; break;
...
case 9: .........; break;
}

Я надеюсь, что смогу сделать что-то вроде:

switch (number)
{
case (1 to 4): do the same for all of them; break;
case (5 to 9): again, same thing for these numbers; break;
}

1
Вы можете использовать if-else для такого сценария
Satpal

Ответы:


226

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

Пример:

int i = 63;

switch (i)
{
    case int n when (n >= 100):
        Console.WriteLine($"I am 100 or above: {n}");
        break;

    case int n when (n < 100 && n >= 50 ):
        Console.WriteLine($"I am between 99 and 50: {n}");
        break;

    case int n when (n < 50):
        Console.WriteLine($"I am less than 50: {n}");
        break;
}

Примечания:

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

10
Вы, сэр, мой герой. Я хотел подчеркнуть это ругательством, но не лучше. :)
Gawie Greef

2
(И )вокруг whenусловия не нужны. Т.е. case int n when n >= 100:тоже работает.
Уве Кейм

6
Даже varделает работу: Т.е. case var n when n >= 100:.
Уве Кейм

9
@JamesKo Я думаю, что это чисто и улучшает читаемость по сравнению с кучей операторов if, особенно если у вас более 3-4 условий.
Суббота,

1
Намного лучше, чем набор операторов if, он намного чище.
John Stock

44

Вот лучшее и элегантное решение вашей проблемы.

int mynumbercheck = 1000;
// Your number to be checked
var myswitch = new Dictionary <Func<int,bool>, Action>
            { 
             { x => x < 10 ,    () => //Do this!...  },  
             { x => x < 100 ,    () => //Do this!...  },
             { x => x < 1000 ,    () => //Do this!...  },
             { x => x < 10000 ,   () => //Do this!... } ,
             { x => x < 100000 ,  () => //Do this!... },
             { x => x < 1000000 ,  () => //Do this!... } 
            };

Теперь вызовем наш условный переключатель

   myswitch.First(sw => sw.Key(mynumbercheck)).Value();

Альтернатива Switch / ifElse


1
@Akxaya Я все еще думаю, что переключатель должен быть расширен в C #, но это выглядит фантастически и, похоже, действительно хорошо работает. Спасибо, что поделились этим примером. Спасибо
WonderWorker

Это неясный ответ на вопрос о переключателе / ​​случае.
Pointer Null

13
Словарь не сохраняет и не возвращает значения в том порядке, в котором они были добавлены. Это работает с компилятором Microsoft, но можно легко написать соответствующий компилятор там, где он не работает. Вместо этого используйте List <KeyValuePair <Func <int, bool>, Action >>. Также имейте в виду, что создание структуры данных связано с расходами, поэтому, вероятно, это должен быть статический член, доступный только для чтения.
Натан Филлипс

@PointerNull: пожалуйста, укажите в блоге необходимый код, написанный в комментариях для использования в будущем
Akxaya

@NathanPhillips: спасибо, что подняли этот вопрос. Surly, коллекция IList также была бы альтернативой. это был всего лишь пример, который я реализовал со сложными параметрами с помощью List <t>.
Akxaya

13

Я бы использовал тернарные операторы для классификации условий переключения.

Так...

switch( number > 9 ? "High" :
        number > 5 ? "Mid" :
        number > 1 ? "Low" : "Floor")
        {
              case "High":
                    do the thing;
                    break;
               case "Mid":
                    do the other thing;
                    break;
               case "Low":
                    do something else;
                    break;
               case "Floor":
                    do whatever;
                    break;
         }

12

Чтобы завершить поток, вот синтаксис C # 8:

  var percent = price switch
  {
    var n when n >= 1000000 => 7f,
    var n when n >= 900000 => 7.1f,
    var n when n >= 800000 => 7.2f,
    _ => 0f // default value
  };

Если вы хотите указать диапазоны:

  var percent2 = price switch
  {
    var n when n >= 1000000 => 7f,
    var n when n < 1000000 && n >= 900000 => 7.1f,
    var n when n < 900000 && n >= 800000 => 7.2f,
    _ => 0f // default value
  };

8

В этом случае следует использовать if-else. Но если по какой-либо причине по-прежнему требуется переключение, вы можете сделать, как показано ниже, первые случаи без разрыва будут распространяться до первого разрыва. Как предполагалось в предыдущих ответах, я рекомендую переключатель if-else.

switch (number){
            case 1:
            case 2:
            case 3:
            case 4: //do something;
                    break;
            case 5:
            case 6:
            case 7:
            case 8:
            case 9: //Do some other-thing;
                   break;
        }

8

Вы могли бы switchсоздать диапазоны «дескрипторов», используя их вместе с Listвашими границами.

List<int> bounds = new List<int>() {int.MinValue, 0, 4, 9, 17, 20, int.MaxValue };

switch (bounds.IndexOf(bounds.Last(x => x < j)))
{
    case 0: // <=0
        break;

    case 1: // >= 1 and <=4
        break;
    case 2: // >= 5 and <=9
        break;
    case 3: // >= 10 and <=17
        break;
    case 4: // >= 18 and <=20
        break;

    case 5: // >20
        break;
}

При таком подходе диапазоны могут иметь разные пролеты.


6

Интервал постоянный:

 int range = 5
 int newNumber = number / range;
 switch (newNumber)
 {
      case (0): //number 0 to 4
                break;
      case (1): //number 5 to 9
                break;
      case (2): //number 10 to 14
                break;
      default:  break;
 }

В противном случае:

  if else

3

Как уже упоминалось, if-elseбыло бы лучше в этом случае, когда вы будете обрабатывать диапазон:

if(number >= 1 && number <= 4)
{
   //do something;
}
else if(number >= 5 && number <= 9)
{
   //do something else;
}

2

В .Net только Visual Basic допускает диапазоны в операторах switch, но в C # для этого нет допустимого синтаксиса.

Решая вашу конкретную проблему на C #, я бы решил ее так:

if(number >= 1 && number <= 9) // Guard statement
{
    if(number < 5)
    {
        // Case (1 to 4):

        //break;

    }
    else
    {
        // Case (5 to 9):

        //break;

    }

}
else
{
    // Default code goes here

    //break;

}

Чтобы проиллюстрировать это дальше, представьте, что у вас есть процентное значение.

Используя вашу проблему в качестве шаблона, вы можете пожелать, чтобы это выглядело так:

switch (percentage)
{
    case (0 to 19):
        break;

    case (20 to 39):
        break;

    case (40 to 69):
        break;

    case (70 to 79):
        break;

    case (80 to 100):
        break;

    default:
        break;

}

Однако, поскольку C # не поддерживает этот синтаксис, вот решение, которое позволяет C #:

if (percentage >= 0 && percentage <= 100) // Guard statement
{
    if (percentage >= 40)
    {
        if (percentage >= 80)
        {
            // Case (80% to 100%)

            //break;

        }
        else
        {
            if (percentage >= 70)
            {
                // Case (70% to 79%)

                //break;

            }
            else
            {
                // Case (40% to 69%)

                //break;

            }

        }

    }
    else
    {
        if (percentage >= 20)
        {
            // Case (20% to 39%)

            //break;

        }
        else
        {
            // Case (0% to 19%)

            //break;

        }

    }

}
else
{
    // Default code goes here

    //break;

}

К этому нужно немного привыкнуть, но когда вы это получите, все будет в порядке.

Лично я приветствовал бы операторы switch, разрешающие диапазоны.

Будущее операторов переключения C #

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

Версия А

switch(value)
{
    case (x => x >= 1 && x <= 4):
    break;

    case (x => x >= 5 && x <= 9):
    break;

    default:
    break;

}

Версия B

switch(param1, param2, ...)
{
    case (param1 >= 1 && param1 <= 4):
    break;

    case (param1 >= 5 && param1 <= 9 || param2 != param1):
    break;

    default:
    break;

}

1

Если вы используете C / C ++, синтаксиса «диапазона» не существует. Вы можете перечислить все значения только после каждого сегмента «case». Язык Ада или Паскаль поддерживают синтаксис диапазона.


0

Прежде всего, вы должны указать язык программирования, о котором говорите. Во-вторых, switchоператоры правильно используются для закрытых наборов опций, касающихся переключаемой переменной, например перечислений или предопределенных строк. В этом случае я бы предложил использовать старую добрую if-elseструктуру.


0

Через switchcase это невозможно. Можно использовать вложенные операторы if.

if(number>=1 && number<=4){
//Do something
}else if(number>=5 && number<=9){
//Do something
}

А что насчет старого доброго, (number >= 1 && number <= 4)вместо того, чтобы проверять каждый номер? Как бы вы написали от 1 до 120 ? ;-)
DarkDust

О, и обратить внимание на =против ==.
DarkDust

-1

Если вопрос был о C (вы не сказали), то ответ отрицательный, но : GCC и Clang (возможно, другие) поддерживают синтаксис диапазона , но это не действует ISO C:

switch (number) {
    case 1 ... 4:
        // Do something.
        break;

    case 5 ... 9:
        // Do something else.
        break;
}

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


Pascal / delphi тоже делает это. номер дела 1..4: сделать что-нибудь; и т. д.
Kell

Вопрос по C #
SuB

@SuB: Я знаю. Я добавил тег C # к этому вопросу после того, как OP наконец сообщил нам, о каком языке идет речь. Но ответ может быть полезен людям, которые приходят сюда через поисковую систему, поэтому я не удалил его.
DarkDust

-1

В C # кейсы переключения - это, по сути, словари о том, что делать дальше. Поскольку вы не можете найти диапазон в словаре, лучшее, что вы можете сделать, - это случай ... когда сказал Стив Гомес.


-3

Вы можете использовать операторы if-else с || операторы (или-оператор), например:

if(case1 == true || case2 == true || case3 == true)
   {
    Do this!... 
   }
else if(case4 == true || case5 == true || case6 == true)
   {
    Do this!... 
   }
else if(case7 == true || case8 == true || case9 == true)
   {
    Do this!... 
   }

Вау, это немного сложно для чего-то вроде if (number >= 1 && number <= 4) { … } else if (number >= 5 && number <= 9) { … }, тебе не кажется?
DarkDust

Хорошо, да ... Эм, но если кейсы, которые должны делать то же самое, не заказаны, вам нужно использовать '|| оператор '...
Лукас Варсиц

Но его целью было проверить, находится ли число в пределах диапазона, поэтому порядок не имеет значения (за исключением проверенных диапазонов ).
DarkDust

Это не ошибка , ваше решение не ошибочное, а просто сложное ;-)
DarkDust

== true: face_palm: это поведение по умолчанию, а для == false вы можете использовать оператор not
Et7f3XIV
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.