В чем польза / минус использования switch
оператора по сравнению с if/else
C #. Я не могу представить, что есть такая большая разница, кроме, возможно, внешнего вида вашего кода.
Есть ли какая-то причина, по которой результирующий IL или связанная с ним производительность во время выполнения будут радикально отличаться?
Связанный: Что быстрее, включить строку или еще тип?
c#
.net
switch-statement
Мэтью М. Осборн
источник
источник
Ответы:
Оператор SWITCH производит только ту же сборку, что и IF в режиме отладки или совместимости. В выпуске он будет скомпилирован в таблицу переходов (через оператор MSIL 'switch') - это O (1).
C # (в отличие от многих других языков) также позволяет включать строковые константы - и это работает немного по-другому. Очевидно, что создавать таблицы переходов для строк произвольной длины непрактично, поэтому чаще всего такой переключатель будет скомпилирован в стек IF.
Но если число условий достаточно велико, чтобы покрыть накладные расходы, компилятор C # создаст объект HashTable, заполнит его строковыми константами и выполнит поиск в этой таблице, а затем выполнит переход. Поиск Hashtable не является строго O (1) и имеет заметные постоянные затраты, но если количество меток падежа велико, это будет значительно быстрее, чем сравнение с каждой строковой константой в IF.
Подводя итог, если число условий больше 5 или около того, предпочитайте SWITCH, чем IF, в противном случае используйте то, что выглядит лучше.
источник
В целом (с учетом всех языков и всех компиляторов) оператор switch МОЖЕТ СОДЕРЖАТЬ, когда оператор if / else более эффективен, поскольку компилятору легко генерировать таблицы переходов из операторов switch. То же самое можно сделать для операторов if / else с учетом соответствующих ограничений, но это гораздо сложнее.
В случае C # это также верно, но по другим причинам.
С большим количеством строк есть существенное преимущество в производительности при использовании оператора switch, потому что компилятор будет использовать хеш-таблицу для реализации перехода.
При небольшом количестве строк производительность между ними одинакова.
Это связано с тем, что в этом случае компилятор C # не создает таблицу переходов. Вместо этого он генерирует MSIL, который эквивалентен блокам IF / ELSE.
Существует инструкция MSIL «оператор переключения», которая при соединении будет использовать таблицу переходов для реализации оператора переключения. Однако он работает только с целочисленными типами (этот вопрос касается строк).
Для небольшого числа строк компилятору более эффективно генерировать блоки IF / ELSE, чем использовать хеш-таблицу.
Когда я первоначально заметил это, я сделал предположение, что поскольку блоки IF / ELSE использовались с небольшим количеством строк, компилятор сделал то же самое преобразование для большого количества строк.
Это было НЕПРАВИЛЬНО. «IMA» был достаточно любезен, чтобы указать мне на это (ну ... он не был добр в этом, но он был прав, а я был неправ, что является важной частью)
Я также сделал предположение о том, что в MSIL отсутствует инструкция «switch» (я подумал, что если есть примитив switch, почему они не используют его с хэш-таблицей, поэтому не должно быть примитива switch. ...) Это было неправильно и невероятно глупо с моей стороны. И снова «IMA» указал мне на это.
Я сделал обновления здесь, потому что это пост с самым высоким рейтингом и принятый ответ.
Тем не менее, я сделал это вики-сообществом, потому что считаю, что не заслуживаю REP за то, что был неправ. Если у вас есть шанс, пожалуйста, проголосуйте за пост Има.
источник
Три причины, чтобы предпочесть
switch
:Компилятор, нацеленный на нативный код, часто может скомпилировать оператор switch в одну условную ветвь плюс косвенный переход, тогда как для последовательности
if
s требуется последовательность условных ветвей . В зависимости от плотности дел было написано очень много научных статей о том, как эффективно составлять описания дел; некоторые связаны со страницей компилятора lcc . (У Lcc был один из самых инновационных компиляторов для коммутаторов.)Оператор switch является выбором среди взаимоисключающих альтернатив, а синтаксис переключателя делает этот поток управления более прозрачным для программиста, чем набор операторов if-then-else.
В некоторых языках, включая, безусловно, ML и Haskell, компилятор проверяет, не были ли вы исключены какие-либо случаи . Я рассматриваю эту функцию как одно из главных преимуществ ML и Haskell. Я не знаю, может ли C # сделать это.
Анекдот: на лекции, которую он прочитал, получив награду за пожизненные достижения, я услышал, как Тони Хоар сказал, что из всего, что он делал в своей карьере, были три, которыми он больше всего гордился:
case
оператором)Я не могу представить себе жизнь без
switch
.источник
Компилятор собирается оптимизировать практически все в один и тот же код с небольшими отличиями (Кнут, кто-нибудь?).
Разница в том, что оператор switch является более чистым, чем пятнадцать операторов if, соединенных вместе.
Друзья не позволяют друзьям составлять операторы if-else.
источник
На самом деле, оператор switch более эффективен. Компилятор оптимизирует его до таблицы поиска, где с помощью операторов if / else он не может. Недостатком является то, что оператор switch нельзя использовать со значениями переменных.
Вы не можете сделать:
должно быть
источник
Я не видел, чтобы кто-то еще поднимал (очевидный?) Вопрос о том, что предполагаемое преимущество в эффективности оператора switch зависит от того, насколько разные случаи примерно одинаково вероятны. В случаях, когда одно (или несколько) значений гораздо более вероятны, лестница if-then-else может быть намного быстрее, гарантируя, что сначала проверяются самые распространенные случаи:
Так, например:
против
Если x равен нулю 90% времени, код if-else может быть в два раза быстрее кода на основе коммутатора. Даже если компилятор превратит «переключатель» в какое-то умное движение на основе таблиц, это все равно будет не так быстро, как простая проверка на ноль.
источник
switch
совместимы,switch
утверждение лучше (более читабельно, иногда быстрее). Если вы знаете, что один случай гораздо более вероятен, вы можете извлечь его, чтобы сформироватьif
-else
-switch
конструкцию, и, если он заметно быстрее , вы оставите это в. Еслиswitch
выродится и станет слишком маленьким, регулярное выражение-замена выполнит большую часть работы по преобразованию его вelse if
-цепь.часто это будет выглядеть лучше - то есть будет легче понять, что происходит. Учитывая, что выигрыш в производительности в лучшем случае будет крайне минимальным, наиболее важным отличием является представление кода.
Так что, если if / else выглядит лучше, используйте его, в противном случае используйте оператор switch.
источник
Побочная тема, но я часто переживаю (и чаще вижу)
if
/else
иswitch
утверждение становится слишком большим со слишком большим количеством случаев. Они часто вредят ремонтопригодности.Общие виновники включают в себя:
Исправить:
источник
Согласно этой ссылке, сравнение IF и Switch итерационного теста с использованием оператора switch и if аналогично 1 000 000 000 итераций, время, затраченное оператором Switch = 43,0 с, и оператором If = 48,0 с.
Это буквально 20833333 итераций в секунду, так что, если мы действительно должны сосредоточиться больше,
PS: Просто чтобы узнать разницу в производительности для небольшого списка условий.
источник
Если вы просто используете оператор if or else, базовое решение использует сравнение? оператор
Вы можете сделать или рутина в выключатель
источник
На самом деле это не отвечает на ваш вопрос, но, учитывая, что между скомпилированными версиями будет мало различий, я бы настоятельно призвал вас написать свой код так, чтобы он наилучшим образом описывал ваши намерения. Мало того, что у компилятора больше шансов делать то, что вы ожидаете, но и другим будет проще поддерживать ваш код.
Если вы намерены разветвить свою программу на основе значения одной переменной / атрибута, то оператор switch лучше всего отражает это намерение.
Если вы намерены разветвлять вашу программу на основе различных переменных / атрибутов / условий, тогда цепочка if / else if лучше всего отражает это намерение.
Я признаю, что Коди прав в том, что люди забывают команду break, но почти так же часто я вижу, что люди делают сложные, если блоки, где они ошибаются в {}, так что строки, которые должны быть в условном выражении, - нет. Это одна из причин, по которой я всегда включаю {} в свои операторы if, даже если в нем есть одна строка. Мало того, что это легче читать, но если мне нужно добавить еще одну строку в условной, я не могу забыть добавить ее.
источник
Интересный вопрос. Это возникло несколько недель назад на работе, и мы нашли ответ, написав фрагмент кода и просмотрев его в .NET Reflector (рефлектор потрясающий !! Мне очень нравится).
Вот что мы обнаружили: допустимый оператор switch для чего-либо, кроме строки, компилируется в IL как оператор switch. Однако, если это строка, она переписывается как if / else if / else в IL. Поэтому в нашем случае мы хотели узнать, как операторы switch сравнивают строки, например, учитывает ли регистр и т. Д., И рефлектор быстро дал нам ответ. Это было полезно знать.
Если вы хотите выполнять сравнение строк с учетом регистра, вы можете использовать оператор switch, так как это быстрее, чем выполнение String.Compare в if / else. (Правка: читать « Что быстрее», включить строку или elseif для типа? Для некоторых реальных тестов производительности) Однако, если вы хотите сделать регистр нечувствительным, тогда лучше использовать if / else, так как полученный код не симпатичен.
Лучшее практическое правило - использовать операторы switch, если это имеет смысл (серьезно), например:
Если вам нужно манипулировать значением для подачи в оператор switch (создать временную переменную для переключения), то вам, вероятно, следует использовать оператор управления if / else.
Обновление:
На самом деле лучше преобразовать строку в верхний регистр (например
ToUpper()
), поскольку, очевидно, существуют дополнительные оптимизации, которые компилятор точно в срок может делать по сравнению сToLower()
. Это микрооптимизация, но в узком кругу это может быть полезно.Небольшое примечание:
Чтобы улучшить читаемость операторов switch, попробуйте следующее:
источник
Оператор switch определенно быстрее, чем if if if. Есть скоростные испытания, которые были предоставлены на нем BlackWasp
http://www.blackwasp.co.uk/SpeedTestIfElseSwitch.aspx
- Проверьте это
Но сильно зависит от возможностей, которые вы пытаетесь объяснить, но я стараюсь использовать оператор switch всякий раз, когда это возможно.
источник
Я думаю, не только C #, но и все языки на основе C: поскольку переключение ограничено константами, можно генерировать очень эффективный код, используя «таблицу переходов». Случай C на самом деле является старым добрым вычисляемым GOTO на FORTRAN, но случай C # все еще проверяет константу.
Это не тот случай, когда оптимизатор сможет сделать тот же код. Рассмотрим, например,
Поскольку это составные логические значения, сгенерированный код должен вычислять значение и короткую замыкание. Теперь рассмотрим эквивалент
Это может быть скомпилировано в
потому что вы неявно говорите компилятору, что ему не нужно вычислять OR и тесты на равенство.
источник
Мой преподаватель кафедры предложил вам не менять формулировки, поскольку люди часто забывают перерыв или используют его неправильно. Я не могу вспомнить точно, что он сказал, но что-то похожее на то, что взгляд на некоторую основную кодовую базу, которая показывала примеры оператора switch (много лет назад), также содержал массу ошибок.
источник
Что-то, что я только что заметил, это то, что вы можете комбинировать операторы if / else и switch! Очень полезно, когда нужно проверить предварительные условия.
источник
Я думаю, что переключение происходит быстрее, чем если условия вроде того, как посмотреть, есть ли такая программа:
Напишите программу для ввода любого числа (от 1 до 99) и проверьте, в каком слоте a) 1 - 9, затем слот один b) 11 - 19, затем слот два c) 21-29, затем слот три и так далее до 89- 99
Затем включите, если вам нужно выполнить много условий, но вы должны просто набрать текст.
это будет так легко
Таких примеров еще много!
источник
оператор switch в основном представляет собой сравнение на равенство. События клавиатуры имеют большое преимущество по сравнению с оператором switch, когда в нем легко писать и читать код, тогда как в случае оператора if else отсутствие скобки {} также может вызывать беспокойство.
Оператор if elseif подходит для более чем одного решения, если (theAmountOfApples больше 5 &&; themountOfApples меньше 10) сохраняют ваши яблоки, иначе, если (theAmountOfApples больше 10 || theAmountOfApples == 100) продают ваши яблоки. Я не пишу на C # или C ++, но я изучил его до того, как выучил Java, и это близкие языки.
источник
Одним из возможных недостатков операторов switch является отсутствие нескольких условий. Вы можете иметь несколько условий для операторов if (else), но не несколько случаев с разными условиями в переключателе.
Операторы switch не подходят для логических операций, выходящих за рамки простых булевых уравнений / выражений. Для этих булевых уравнений / выражений это в высшей степени подходит, но не для других логических операций.
У вас гораздо больше свободы с логикой, доступной в операторах If, но читаемость может пострадать, если инструкция If становится громоздкой или плохо обрабатывается.
У обоих есть место в зависимости от контекста того, с чем вы столкнулись.
источник