Есть ли существенная разница между использованием if / else и switch-case в C #? - PullRequest
198 голосов
/ 28 декабря 2008

В чем польза / недостаток использования оператора switch по сравнению с if/else в C #. Я не могу представить, что есть такая большая разница, кроме, может быть, внешний вид вашего кода.

Есть ли какая-либо причина, по которой результирующая производительность IL или связанная с ней производительность во время выполнения будут радикально отличаться?

Связанный: Что быстрее, включить строку или еще тип?

Ответы [ 20 ]

2 голосов
/ 28 декабря 2008

Это на самом деле не отвечает на ваш вопрос, но, учитывая, что между скомпилированными версиями будет мало различий, я настоятельно призываю вас написать свой код так, чтобы он наилучшим образом описывал ваши намерения. Мало того, что у компилятора больше шансов делать то, что вы ожидаете, но и другим будет проще поддерживать ваш код.

Если вы намереваетесь выполнить ветвь вашей программы на основе значения одной переменной / атрибута, тогда оператор switch лучше всего отражает это намерение.

Если вы намерены разветвить вашу программу на основе различных переменных / атрибутов / условий, тогда цепочка if / else if лучше всего отражает это намерение.

Я признаю, что cody прав в том, что люди забывают команду break, но почти так же часто я вижу, что люди делают сложные, если блоки, где они ошибаются в {}, так что строки, которые должны быть в условном выражении, - нет. Это одна из причин, по которой я всегда включаю {} в свои операторы if, даже если в нем есть одна строка. Мало того, что это легче читать, но если мне нужно добавить еще одну строку в условной, я не могу забыть добавить ее.

2 голосов
/ 27 октября 2013

По этой ссылке IF против Switch сравнение итерационного теста с использованием оператора switch и if аналогично 1 000 000 000 итераций, время, затраченное на Switch Statement = 43.0s & by If Statement = 48.0s

Что буквально 20833333 итераций в секунду, поэтому, если нам действительно нужно сосредоточиться больше,

P.S .: Просто чтобы узнать разницу в производительности для небольшого списка условий.

1 голос
/ 28 декабря 2008

Я думаю, что не только C #, но и все языки на основе C: поскольку переключение ограничено константами, можно генерировать очень эффективный код, используя «таблицу переходов». Случай C на самом деле является старым добрым вычисляемым GOTO на FORTRAN, но случай C # по-прежнему проверяет константу.

Это не тот случай, когда оптимизатор сможет сделать тот же код. Рассмотрим, например,

if(a == 3){ //...
} else if (a == 5 || a == 7){ //...
} else {//...
}

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

switch(a){
   case 3: // ...
    break;
   case 5:
   case 7: //...
    break;
   default: //...
}

Это может быть скомпилировано в

BTABL: *
B3:   addr of 3 code
B5:
B7:   addr of 5,7 code
      load 0,1 ino reg X based on value
      jump indirect through BTABL+x

потому что вы неявно говорите компилятору, что ему не нужно вычислять ИЛИ и тесты на равенство.

1 голос
/ 28 декабря 2008

Интересный вопрос. Это возникло несколько недель назад на работе, и мы нашли ответ, написав пример фрагмента и просмотрев его в .NET Reflector (рефлектор потрясающий !! Мне очень нравится).

Вот что мы обнаружили: Действительный оператор switch для чего-либо, кроме строки, компилируется в IL как оператор switch. Однако, если это строка, она переписывается как if / else if / else в IL. Поэтому в нашем случае мы хотели узнать, как операторы switch сравнивают строки, например, учитывает регистр и т. Д., И рефлектор быстро дал нам ответ. Это было полезно знать.

Если вы хотите выполнять сравнение строк с учетом регистра, то вы могли бы использовать оператор switch, поскольку он быстрее, чем выполнение String.Compare в if / else. (Редактировать: Читать Что быстрее, включить строку или другое в типе? для некоторых реальных тестов производительности) Однако, если вы хотите сделать регистр нечувствительным, тогда лучше использовать if / else в качестве результата код не красивый

switch (myString.ToLower())
{
  // not a good solution
}

Лучшее практическое правило - использовать операторы switch, если это имеет смысл (серьезно), например:

  • улучшает читабельность вашего кода
  • вы сравниваете диапазон значений (float, int) или enum

Если вам нужно манипулировать значением для подачи в оператор switch (создать временную переменную для переключения), то вам, вероятно, следует использовать оператор управления if / else.

Обновление:

На самом деле лучше преобразовать строку в верхний регистр (например, ToUpper()), поскольку очевидно, что есть дополнительные оптимизации, которые компилятор "точно в срок" может делать по сравнению с ToLower(). Это микрооптимизация, однако в узком кругу это может быть полезно.


Небольшое примечание:

Чтобы улучшить читаемость операторов switch, попробуйте следующее:

  • поставить наиболее вероятную ветвь первой, т.е. наиболее доступную
  • если они все могут произойти, перечислите их в алфавитном порядке, чтобы их было легче найти.
  • никогда не использовать стандартную перехват для последнего оставшегося условия, это лениво и вызовет проблемы позже в жизни кода.
  • использовать стандартную перехват для утверждения неизвестного условия, даже если это вряд ли когда-либо произойдет. вот для чего хороши утверждения.
0 голосов
/ 19 июня 2017

Одним из возможных недостатков операторов switch является отсутствие нескольких условий. Вы можете иметь несколько условий для операторов if (else), но не несколько случаев с разными условиями в переключателе.

Операторы переключения не подходят для логических операций, выходящих за рамки простых булевых уравнений / выражений. Для этих булевых уравнений / выражений он особенно подходит, но не для других логических операций.

У вас гораздо больше свободы с логикой, доступной в операторах If, но читаемость может пострадать, если инструкция If становится громоздкой или плохо обрабатывается.

У обоих есть место в зависимости от контекста, с которым вы столкнулись.

0 голосов
/ 05 апреля 2016

я знаю, что это не совсем вопрос, но мне действительно нужно отметить, что когда вы думаете об эффективности на этом уровне, вам может понадобиться больше абстракции в вашем коде. Вам больше не понадобится переключать регистры, особенно если он содержит логику. (мой пример в php).

    $feeMapping = [
        1000 => 1,
        2000 => 2,
        3000 => 3,
        4000 => 4,
        5000 => 5,
        6000 => 6,
        7000 => 7
    ];

    function findFee($feeMapping, $amount) {
        foreach ($feeMapping as $fee => $value) {
            if ($value >= $amount) {
                return $fee;
            }
        }

        return 7;
    }

    $feeValue = findFee($feeMapping, 200);

Теперь посмотрите на избыточность аналогичного кода!

    if ($amount >= 1000) {
        return 1;
    } elseif ($amount >= 2000) {
        return 2;
    } elseif ($amount >= 3000) {
        return 3;
    } elseif ($amount >= 4000) {
        return 4;
    } elseif ($amount >= 5000) {
        return 5;
    } elseif ($amount >= 6000) {
        return 6;
    } else {
        return 7;
    }
0 голосов
/ 25 апреля 2015

оператор switch в основном представляет собой сравнение на равенство. События клавиатуры имеют большое преимущество по сравнению с оператором switch, когда легко писать и читать код, тогда как оператор if elseif пропускает {скобку}, что также может вызывать беспокойство.

char abc;
switch(abc)
{
case a: break;
case b: break;
case c: break;
case d: break;
}

Оператор if elseif подходит для более чем одного решения, если (theAmountOfApples больше 5 && theAmountOfApples меньше 10) сохраняет ваши яблоки иначе, если (theAmountOfApples больше 10 || theAmountOfApples == 100) продают ваши яблоки. Я не пишу на c # или c ++, но я изучил его до того, как выучил java, и это близкие языки.

0 голосов
/ 29 августа 2014

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

Напишите программу для ввода любого числа (от 1 до 99) и проверьте, находится ли он в каком слоте a) 1 - 9, затем в слот один b) 11 - 19, затем в слот два c) 21-29, затем в слот три и так далее до 89-99

Затем включите, если вам нужно выполнить много условий, кроме случая переключения сынка, вам нужно просто набрать

Переключатель (№ / 10)

и в случае 0 = 1-9, в случае 1 = 11-19 и т. Д.

Это будет так просто

Есть еще много таких примеров!

0 голосов
/ 28 декабря 2008

Мой преподаватель кафедры предложил вам не менять формулировки, поскольку люди часто забывают перерыв или используют его неправильно. Я не могу вспомнить точно, что он сказал, но что-то похожее на то, что взгляд на некоторую основную кодовую базу, которая показывала примеры оператора switch (много лет назад), также содержал массу ошибок.

0 голосов
/ 02 октября 2009

Я только что заметил, что вы можете комбинировать операторы if / else и switch! Очень полезно, когда нужно проверить предварительные условия.

if (string.IsNullOrEmpty(line))
{
    //skip empty lines
}
else switch (line.Substring(0,1))
{
    case "1":
        Console.WriteLine(line);
        break;
    case "9":
        Console.WriteLine(line);
        break;
    default:
        break;
}
...