Корпус комутатора: чи можу я використовувати діапазон замість одного числа


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
Ви можете використовувати , якщо- то ще для такого сценарію
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, це набагато чистіше.
Джон Сток,

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

Це не чітка відповідь на діапазон у питанні перемикача / випадку.
Нуль покажчика

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

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

@NathanPhillips: спасибі, що підняли це питання. Незрозуміло, колекція 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, але якщо з будь-якої причини все ще потрібен перемикач, ви можете зробити, як зазначено нижче, перші випадки без перерви будуть поширюватися до першої перерви. Як пропонували попередні відповіді, я рекомендую переключити інший варіант.

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 дозволяє діапазони в операторах перемикання, але в 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;

}

Це може зайняти трохи звикання, але це прекрасно, як тільки ви це отримаєте.

Особисто я би вітав оператори перемикання, щоб дозволити діапазони.

Майбутнє операторів перемикання C #

Ось кілька ідей, які я мав про те, як можна вдосконалити оператори перемикання:

Версія А

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 ++, синтаксис "діапазону" відсутній. Ви можете перерахувати всі значення лише після кожного сегмента "справи". Синтаксис діапазону підтримки мови Ada або Pascal.


0

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


0

У switchвипадку це неможливо. Ви можете використовувати вкладені оператори 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: зробити щось; тощо
Келл,

Питання про 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

О гаразд так ... Емм, але якщо справи, які повинні робити те саме, не замовлені, вам потрібно використовувати '|| оператор '...
Lukas Warsitz

Але його метою було перевірити, чи не перебуває число в межах діапазону, тому порядок не має значення (крім перевірених діапазонів ).
DarkDust

Це не помилка , ваше рішення не неправильне, просто складне ;-)
DarkDust

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