Что лучше использовать if или switch
Эстетическая красота: Switch vs If
Вводная
Немного нюансов
Речь ниже пойдет о сравнении оператора switch и его конкретной реализаций на языке Java и операторами if в виде оппонентов этой конструкции. О том, что у оператора switch имеется туз в рукаве — производительность (за редким исключением), пожалуй, знает каждый и этот момент рассматриваться не будет — так как крыть его нечем. Но все же, что не так?
1. Многословность и громоздкость
Среди причин, отталкивающих меня от использования оператора switch — это многословность и громоздкость самой конструкции, только взгляните — switch, case, break и default, причем опускаю за скобки, что между ними, наверняка, еще встретится return и throw. Не подумайте, что призываю не использовать служебные слова языка java или избегать их большого количества в коде, нет, лишь считаю, что простые вещи не должны быть многословными. Вот небольшой пример того, о чем говорю:
Итого для меня: switch/case/default VS if.
Если спросить, кому какой нравится больше код, то большинство отдаст предпочтение 1ому варианту, в то время как по мне, он — многословный. Речь о рефакторинге кода здесь не идет, все мы знаем, что можно было бы использовать константу типа EnumMap или IdentityHashMap для поиска списка по ключу channel или вообще убрать нужные данные в сам Channel, хотя это решение дискуссионное. Но вернемся.
2. Отступы
Возможно в академических примерах использование оператора swicth — это единственная часть кода, но тот код, с которым приходится сталкиваться, поддерживать — это более сложный, обросший проверками, хаками, где-то просто предметной сложностью код. И лично меня, каждый отступ в таком месте напрягает. Обратимся к ‘живому’ примеру (убрал лишнее, но суть осталась).
Итого для меня: 5 отступов VS 2.
Но опять, кому какой нравится вариант? Большинство отдаст предпочтение getReference1.
Отдельно стоит отметить, что количество отступов еще зависит от выбранного стиля форматирования кода.
3. Проверка на null
Если используется оператор switch со строками или енумами параметр выбора необходимо проверять на null. Вернемся к getTypes примерам.
Итого для меня: лишний код.
Даже если Вы абсолютно уверенны сейчас в том, что null ‘не придет’, это абсолютно не значит, что так будет всегда. Я проанализировал корпоративный багтрэк и нашел этому утверждению подтверждение. Справедливости ради стоит отметить, что структура кода выраженная через if не лишена этой проблемы, зачастую константы для сравнения используются справа, а не слева, например, name.equals(«John»), вместо «John».equals(name). Но в рамках данной статьи, по этому пункту, хотел сказать, что при прочих равных, подход со switch раздувается проверкой на null, при if же проверка не нужна. Добавлю еще, что статические анализаторы кода легко справляются с возможными null-багами.
4. Разношерстность
Очень часто, при длительном сопровождении кода, кодовая база раздувается и можно легко встретить код, похожий на следующий:
Итого для меня: разный стиль.
Раньше был ‘чистенький’ switch, а теперь switch + if. Происходит, как я называю, смешение стилей, часть кода ‘выбора’ выражена через switch, часть через if. Разумеется никто не запрещает использовать if и switch вместе, если это не касается операции выбора/под выбора, как в приведенном примере.
5. Чей break?
При использовании оператора switch, в case блоках может появиться цикл или на оборот, в цикле — switch, со своими прерываниями процесса обработки. Вопрос, чей break, господа?
Итого для меня: читаемость кода понижается.
Если честно, встречались и куда более запутанные примеры кода.
6. Неуместность
В java 7 появилась возможность использовать оператор switch со строками. Когда наша компания перешла на java 7 — это был настоящий Switch-Бум. Может по этому, а может и по другой причине, но во многих проектах встречаются похожие заготовки:
Итого для меня: появляются неуместные конструкции.
7. Гламурный switch под аккомпанемент хардкода
Немного юмора не помешает.
Заключение
Я не призываю Вас отказываться от оператора switch, местами он действительно хорош собой и лапша из if/if-else/else та еще каша. Но черезмерное его использование где ни попадя, может вызывать недовольство у других разработчиков. И я один из них.
Отдельно хотелось отметить, что c точки зрения понимания кода, у меня нет никаких проблем с switch/case — смысл написанного ясен, но вот с точки зрения восприятия эстетической красоты — есть.
И напоследок. Используйте то, что Вам приходится по душе, опуская за скобки навязанные мнения, главное, чтобы Ваш код был простым, рабочим, красивым и надежным. Всего хорошего.
if \ else vs. switch \ case в C#
Что лучше использовать: if\else или switch\case?
3 ответа 3
Ответ выше не совсем корректный, даже учитывая комментарий.
Если значения лежат рядом, например:
В таком случае компилятор генерирует таблицу переходов (jump table) (IL-код):
Как видно, «дырки» заполнились переходами за конец конструкции switch : IL_009a
Если расстояние между значениями слишком большое для построение одной таблицы, компилятор может разделить их на 2+ таблицы. Например:
Посмотрим что будет в общем случае. Я взял 20 случайных чисел:
В таком случае компилятор их сортирует, и ищет бинарным поиском:
Дополнение для String :
Я попытался создать очень большой switch на 60 строк, но ничего не изменилось.
Оба условных оператора работают с одинаковой скоростью. Так как на уровне машинных команд они преобразуются в одни и те же инструкции.
Выбирать имеет смысл только по вкусу и по задаче.
switch может работать только с одной переменной. У if таких ограничений нет.
На мой взгляд, язык C# слишком высокоуровневый для такого рода оптимизаций.
Пишите читаемый код 😉
Вы задаётесь неправильным вопросом.
Если ваша задача — ускорить вашу программу, то решением этой задачи никогда не будет «заменить свитч на последовательность ифов» или наоборот. Ускорение программы проводится на уровне используемых алгоритмов и структур данных.
Тот факт, что один или другой вариант в тех или иных условиях, на той или иной версии компилятора выполняется на несколько наносекунд быстрее, не стоит потраченных на него байт текста.
Во-первых, вы должны помнить, что ваша главная задача — не выиграть 10 тактов процессора (несчастное переключение контекста стоит намного больше!), а сделать вашу программу понятной. Поэтому вы должны использовать switch там, где это прибавляет читаемости коду, там, где это соответствует тому, что именно вы хотите сказать этим кодом. И использовать if там, где это лучше отражает вашу мысль.
Ну и во-вторых, то, что на одной версии компилятора один из методов выражения одной и той же идеи компилируется в более быстрый код, чем другой метод — штука временная и преходящая. Помните, что в C++ сначала рекомендовалось возвращать значения по ссылке для скорости, а затем пришёл тренд «want speed? pass by value!», и наверняка это поменялось сейчас ещё раз.
Поскольку код имеет одинаковый смысл, то в любом из его вариантов рано или поздно он будет компилироваться в одно и то же. JIT-компилятор C# покамест не генерирует одинаковый объектный код для этих двух случаев, а вот компиляторы C++ уже умеют.
Итак, то, какая из имплементаций скорее, а какая медленнее — это не абсолютное понятие.
Вы не должны жертвовать читаемостью кода ради сиюминутной мизерной выгоды. Пишите не «как скорее», а «как правильнее». Расходы на поддержку плохо написанного кода несравнимо больше выгод от микрооптимизаций.
Что лучше использовать if или switch
А что, switch действительно выигрывает в скорости по сравнению с конструкциями if — else, если значения в нём последовательные?
Например, есть примерно след. участок кода:
Вызов данной функции происходит довольно часто, поэтому интересует, будет ли хоть какой-то полезный выигрыш от использования switch в данном случае?
Не оптимизирует ли всё это дело компилятор так, что выйдет либо одинаковая производительность, либо даже хуже?
| От: | LaptevVV |
Дата: | 05.02.12 15:31 | |
Оценка: | 1 (1) |
| От: | potapov.d |
Дата: | 05.02.12 15:48 | |
Оценка: |
Здравствуйте, Аноним, Вы писали:
А>Приветствую.
А>А что, switch действительно выигрывает в скорости по сравнению с конструкциями if — else, если значения в нём последовательные?
А>Например, есть примерно след. участок кода:
А>
лет пять назад дизассемблировал подобный сниппет. в Release сборке студия данную последовательность if’ов преобразует в switch. (его ассемблерное представление, разумеется)
Здравствуйте, Аноним, Вы писали:
А>Приветствую.
А>А что, switch действительно выигрывает в скорости по сравнению с конструкциями if — else, если значения в нём последовательные?
А>Например, есть примерно след. участок кода:
А>
А>Вызов данной функции происходит довольно часто, поэтому интересует, будет ли хоть какой-то полезный выигрыш от использования switch в данном случае?
А>Не оптимизирует ли всё это дело компилятор так, что выйдет либо одинаковая производительность, либо даже хуже?
А>Использую MS-компилятор.
Помнится даже на баше был гдето ответ. Тут чтоле
| От: | watch-maker |
Дата: | 08.02.12 12:36 | |
Оценка: | 1 (1) |
Здравствуйте, Аноним, Вы писали:
А>Приветствую.
А>А что, switch действительно выигрывает в скорости по сравнению с конструкциями if — else, если значения в нём последовательные?
А>Вызов данной функции происходит довольно часто, поэтому интересует, будет ли хоть какой-то полезный выигрыш от использования switch в данном случае?
Это существенно зависит от распределения значений входных данных. Если какой-либо зависимости в значениях value нет, то switch вполне может быть лучшим вариантом. Если же значение a или b встречаются значительно чаще (например в 95% и 4% случаев соответственно), то if может существенно превосходить в скорости switch.
Это связано с особенностью блока предсказания ветвлений процессора. Последовательные if позволяют ему «обучаться» на входных данных и лучше предсказывать нужную ветку программы. В то же время switch, если компилятор сделал из него таблицу и косвенный переход, будет справляться с этой задачей значительно хуже.
Например, для архитектур x86 и x86-64 подробнее об switch-против-if можно прочитать в «Intel® 64 and IA-32 Architectures Optimization Reference Manual».
Ну и вообще, в таких случаях может быть эффективна гибридная схема:
Для уверенности, что компилятор нас правильно понял, ещё бывает полезно обернуть условие (value == a) во что-то подобное __builtin_expect(value == a, 1) или __assume(value == a). Где __builtin_expect и __assume — соответствующие подсказки оптимизатору.
А>Не оптимизирует ли всё это дело компилятор так, что выйдет либо одинаковая производительность, либо даже хуже?
Универсального ответа тут нет. Но что тебе мешает просто посмотреть сгенерированный код самому? Для того, чтобы сказать, что получился одинаковый код, можно же даже не знать ассемблера.
| От: | Sheridan |
Дата: | 10.02.12 13:16 | |
Оценка: |
Написал на коленке немножко кода для замеров. Меряет в тиках процессора (ну, во всяком случае гугл так говорит).
Методика: берем switch и else if каждого по сотне проверок. Замеряем время отработки цикла из 100000 итераций отдельно для if else, отдельно для switch. И это все замеряем по каждому числу, тоесть обходим каждую ветку ветвления. Выводим результаты по каждому ветвлению и усредненные в конце.
Ну, по коду думается мне будет понятнее.
Для не желающих листать эту простыню — вывод: собирайте с оптимизацией — в этом случае абсолютно без разницы что использовать
В результатах конечно простыня еще та.
Результаты неоптимизированной сборки:
Как видите — вариант с if практически сразу потерял свои позиции и под конец разница с switch на порядок.
А вот результаты сборки с оптимизацией мгновенно ставят все на свои места
| От: | Сыроежка |
Дата: | 10.02.12 13:23 | |
Оценка: |
Здравствуйте, Sheridan, Вы писали:
S>Написал на коленке немножко кода для замеров. Меряет в тиках процессора (ну, во всяком случае гугл так говорит).
На мой взгляд это совершенно бессмиысленное заниятие. Во-первых, часто компилятор для двух конструкций генерирует один и тот же ассемблерный код, если конструкции не сложные. Во-вторых, не каждый if можно заменить предложением switch. И, в-третьих, скорость ни одной программы не страдает от того, используете ли вы if или swicth.
| От: | Sheridan |
Дата: | 10.02.12 13:28 | |
Оценка: |
Здравствуйте, Сыроежка, Вы писали:
С>На мой взгляд это совершенно бессмиысленное заниятие. Во-первых, часто компилятор для двух конструкций генерирует один и тот же ассемблерный код, если конструкции не сложные. Во-вторых, не каждый if можно заменить предложением switch. И, в-третьих, скорость ни одной программы не страдает от того, используете ли вы if или swicth.
Ребе, ну человек задал конкретный вопрос — я на него дал не просто ответ, а вполне себе даже исследование.
С написанными тобой буквами я то согласен и так. Только вот было интересно их както подтвердить
Подтвердил таки?
| От: | watch-maker |
Дата: | 10.02.12 13:46 | |
Оценка: |
Здравствуйте, Sheridan, Вы писали:
S>Написал на коленке немножко кода для замеров. Меряет в тиках процессора (ну, во всяком случае гугл так говорит).
S>Методика: берем switch и else if каждого по сотне проверок. Замеряем время отработки цикла из 100000 итераций отдельно для if else, отдельно для switch. И это все замеряем по каждому числу, тоесть обходим каждую ветку ветвления. Выводим результаты по каждому ветвлению и усредненные в конце.
S>Ну, по коду думается мне будет понятнее.
S>Для не желающих листать эту простыню — вывод: собирайте с оптимизацией — в этом случае абсолютно без разницы что использовать
Тест плохой.
Например, gcc43 просто преобразует функцию test_if в такую:
Вы сравнили скорость работы двух пустых функций.
| От: | batu |
Дата: | 10.02.12 14:08 | |
Оценка: |
Здравствуйте, Sheridan, Вы писали:
S>Написал на коленке немножко кода для замеров. Меряет в тиках процессора (ну, во всяком случае гугл так говорит).
S>Методика: берем switch и else if каждого по сотне проверок. Замеряем время отработки цикла из 100000 итераций отдельно для if else, отдельно для switch. И это все замеряем по каждому числу, тоесть обходим каждую ветку ветвления. Выводим результаты по каждому ветвлению и усредненные в конце.
S>Ну, по коду думается мне будет понятнее.
S>Для не желающих листать эту простыню — вывод: собирайте с оптимизацией — в этом случае абсолютно без разницы что использовать
| От: | batu |
Дата: | 10.02.12 14:10 | |
Оценка: |
| От: | Sheridan |
Дата: | 10.02.12 15:51 | |
Оценка: |
| От: | Sheridan |
Дата: | 10.02.12 16:29 | |
Оценка: |
— оптимизатор г++ слишком хорош для данного случая, а я писал на работе, слишком хотел домой и не подумал об этом. Посыпаю голову пеплом, и все такое.
В общем я нагрузил алгоритм еще одной функцией, которая принимает в себя число-счетчик цикла и на его основе считает всякую фигню. Ну типа полезную работу делает.
Также я на отдельно замеряю среднее количество тиков работы этой функции и вычитаю это потом из результата.
Результат без оптимизаций
и результат с оптимизациями
If или switch().case. Что быстрее
switch case 1 ИЛИ 2
делаю разбор вводимых команд, некоторые обрабатываются похоже, команды однобуквенные, разбираю.
Решение
В первом случае все if будут проверяться всегда.
Во втором случае все case будут пройдены только при а = 4. Например, если а = 2, то отработает только первый case и мы выйдем по break. При а = 3 отработают два первых case.
Решение
if выполняет столько сравнений, сколько у вас вариантов. switch вероятнее всего сделает двоичный поиск и выполнит число сравнений равное двоичному логарифму от числа вариантов. Если внутре у ней неонка jmp по табличке, то и вовсе в одну команду уложится.
Ну и каждое ветвление награждает вас 50% бонусом к шансу получить неверным предсказанием перехода по башке. Что не лучшим образом сказывается на производительности. Поэтому лучше их без нужды не плодить.
Это ты еще duff device не видел
——
А вообще все эти рассуждения о скорости не имеют смысла без привязки к конкретному компилятору и его оптимизации. Если хочется адекватных оценок, то берем компилятор, конкретные ключи компиляции, смотрим ассемблер и делаем выводы. Все остальное от лукавого.
при очень разреженном
при case 0 1 2 3 4
скорее всего switch превратится в таблицу переходов
у Evg в блоге была статья на эту тему
если найду кину ссылку
Добавлено через 1 минуту
очень даже распространенная практика «проваливания»
кстати в шарпе её кастрировали и приходится дублировать код
чаще да
но посмотри на код по ссылке
Добавлено через 2 минуты
Ещё неплохой способ «we need to go deeper»:
Статический хеш или switch-case/if-else для выбора
Добрый день. Положим есть такой код:void parseByType(const QString &data, const QString &type) <.
Что быстрее switch(enum) или if else? На этом занятии поговорим об условных операторах. Что это такое? Представьте, что вам нужно вычислить модуль числа, хранящегося в переменной x. Как это сделать? Очевидно, нужно реализовать такой алгоритм. И в этом алгоритме есть вот такое ветвление программы: при x ) оператор; Если выражение в круглых скобках истинно, то выполняется оператор, записанный в if. Иначе этот оператор не выполняется. Используя этот оператор, запишем программу для вычисления модуля числа: Здесь операция изменения знака переменной x будет выполняться только для отрицательных величин, а положительные просто выводиться в консоль, минуя эту операцию. Какие операторы сравнения существуют в JavaScript и как они работают? Многие из них нам известны из школьного курса математики, это: Истинно, если a больше b Истинно, если a больше или равно b При сравнении значений разных типов JavaScript приводит каждое из них к числу. Например: При сравнении булевых значений: Внимание! Странное сравнение null с нулем: Это просто нужно иметь в виду при программировании логики скриптов. В JavaScript можно выполнять сравнение двух значений с учетом их типа данных. Для этого используется оператор === (три равно). Применяя его к предыдущему примеру, получим: Оба результата дадут ложь – false, так как значения, имеющие разные типы считаются не равными друг другу. Та же ситуация будет и при таком строгом сравнении: Здесь также имеем разные типы данных, поэтому результат – false. А вот если взять строгое неравенство, то получим истину во всех случаях: Вот так можно сравнивать между собой значения с учетом их типов. Теперь, когда мы знаем как сравниваются между собой величины, вернемся к нашему условному оператору if. И предположим, что хотим определить знак числа в переменной x. Конечно, проверку можно записать вот так: Но можно сделать лучше. Смотрите, мы здесь имеем дело со взаимоисключающими условиями, то есть, они не могут произойти одновременно: либо первое, либо второе. Для таких ситуаций можно использовать ключевое слово else – иначе, чтобы ускорить процесс проверки: Теперь, у нас здесь всего одно условие. Если оно истинно, то выполнится первый console.log, а иначе – второй console.log. Такая программа будет работать быстрее. В общем случае, синтаксис оператора if else следующий: if( ) оператор 1; И так как после else можно ставить любой оператор, то предыдущую программу можно записать и так: И вообще таких конструкций if else может быть много. Далее, обратим внимание на такой факт: во всех наших примерах по условию шел один оператор – console.log. Но что если нужно выполнить несколько операторов по некоторому условию? Для этого их нужно заключать в фигурные скобки. Например: Здесь по первым двум условиям выполняется два оператора: присвоение значения переменной sgn и вывод результата в консоль. В последнем else записан только один оператор – вывод в консоль, поэтому здесь фигурные скобки ставить не обязательно. В ряде случаев конструкцию if else удобнее записывать через тернарный условный оператор, который имеет такой синтаксис: Сначала вычисляется условие: если оно истинно, то возвращается значение1, в противном случае – значение2. Например: Получим true, если возраст (age) больше 18, иначе – false. Кстати, проверку из данного примера можно сделать короче, просто прописав здесь оператор > вернет true при возрасте больше 18 и false – в противном случае. Теперь, когда мы разобрались с базовыми моментами проверки условий, сделаем следующий шаг и попробуем реализовать проверку попадания переменной x в диапазон [2; 7], то есть, условие должно быть истинным, когда x принимает значения в этом диапазоне чисел. Очевидно, что здесь должно быть две проверки: первая – мы проверяем, что x >= 2 и вторая – проверяем, что x 7, то делается вывод о невхождении переменной x в указанный диапазон. Вот так можно записывать более сложные условия в условном операторе if. Причем они могут комбинироваться в любом сочетании, например: Здесь реализована проверка, что x должно принадлежать [2; 7], а y не принадлежать [0; 5]. И обратите внимание вот на эти круглые скобки. Дело в том, что приоритет у операции && больше, чем у ||, поэтому без скобок у нас бы получилась вот такая проверка: то есть, мы проверяли бы, что x принадлежит [2; 7] и y меньше нуля ИЛИ y больше 5. Как вы понимаете – это уже совсем другая проверка. Поэтому учитывайте приоритет этих операций при формировании составного условия. Если нужно изменить приоритет – используйте круглые скобки. Внутри условия можно прописывать и такие одиночные выражения: Вот этот восклицательный знак – это отрицание – НЕ, то есть, чтобы проверить, что 0 – это false мы преобразовываем его в противоположное состояние с помощью оператора отрицания НЕ в true и условие срабатывает. Аналогично и с переменной z, которая равна false. Вот так работает оператор if в JavaScript. Второй условный оператор switch используется, когда из множества возможных вариантов нужно выбрать какой-то один. Например, мы хотим проверить: принимает ли некая переменная одно из значений 1, 2, 3 или 4. Это будет выглядеть так: И в консоле увидим, что item=3, 4 и другое значение. Почему так и как это все работает? В круглых скобках оператора switch записывается переменная, которая сравнивается со значениями (константами), указанными в case. Далее, через двоеточие пишутся операторы, которые выполняются при совпадении значения переменной с константой. В нашем случае item=3, срабатывает case 3 и выполняется console.log(«item = 3»). Но, оператор switch в JavaScript реализован так, что все последующие операторы тоже будут выполняться. В ряде случаев это бывает полезно и нужно. Если же мы хотим прервать выполнение оператора switch после успешной проверки, нужно записать оператор break вот так: Теперь в консоле мы видим только строчку item=3. Операторы, стоящие после default выполняются, если не сработала ни одна из проверок. Это необязательное ключевое слово: switch может быть записан и без него, но тогда мы не увидим «item другое значение», если переменная не будет равна 1, 2, 3 или 4. Так когда же использовать условный оператор if, а когда switch? Правило простое: если нужно проверить переменную на равенство множеству значений, то лучше использовать switch – он сработает быстрее, чем if. Во всех других случаях применяется оператор if. В практике программирования в 99% случаев используется if и лишь для некоторых частных проверок – оператор switch. JavaScipt #1: что это такое, с чего начать, как внедрять и запускать JavaScipt #2: способы объявления переменных и констант в стандарте ES6+ JavaScript #3: примитивные типы number, string, Infinity, NaN, boolean, null, undefined, Symbol JavaScript #4: приведение типов, оператор присваивания, функции alert, prompt, confirm JavaScript #6: условные операторы if и switch, сравнение строк, строгое сравнение JavaScript #7: операторы циклов for, while, do while, операторы break и continue JavaScript #8: объявление функций по Function Declaration, аргументы по умолчанию JavaScript #9: функции по Function Expression, анонимные функции, callback-функции JavaScript #10: анонимные и стрелочные функции, функциональное выражение JavaScript #11: объекты, цикл for in JavaScript #12: методы объектов, ключевое слово this JavaScript #13: клонирование объектов, функции конструкторы JavaScript #14: массивы (array), методы push, pop, shift, unshift, многомерные массивы JavaScript #15: методы массивов: splice, slice, indexOf, find, filter, forEach, sort, split, join JavaScript #16: числовые методы toString, floor, ceil, round, random, parseInt и другие JavaScript #18: коллекции Map и Set JavaScript #19: деструктурирующее присваивание JavaScript #20: рекурсивные функции, остаточные аргументы, оператор расширения JavaScript #21: замыкания, лексическое окружение, вложенные функции JavaScript #22: свойства name, length и методы call, apply, bind функций JavaScript #23: создание функций (new Function), функции setTimeout, setInterval и clearInterval © 2021 Частичное или полное копирование информации с данного сайта для распространения на других ресурсах, в том числе и бумажных, строго запрещено. Все тексты и изображения являются собственностью сайта
Может кто нибудь знает,какая конструкция лучше в плане производительности: 1) enum eЧто быстрее, вложенные REPLACE или функция с CASE на va?
Здравствуйте форумчане. Имеется база с приличным количеством записей, порядка миллиона. Задача в.Условные операторы if и switch
Сравнение разных типов данных
Строгое сравнение
else оператор 2;Одиночные проверки
Оператор switch
Видео по теме