Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > .NET Frameworks (точка нет фреймворки) > C# (си шарп)
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 19.02.2013, 11:55   #1
Mixim
Форумчанин
 
Регистрация: 29.10.2009
Сообщений: 259
Вопрос Switch vs If-Else

Приветствую, многоуважаемый народ! На работе встала задача разобраться и исправить чужой код. Полез, вроди бы все ясно и понятно, но дойдя до последнего метода буквально сломал голову. Причиной этому стало то, что в этом методе используется миллион и одна строчка кода if-else из разряда:
Код:
if (a==1)
{
//несколько десятков операторов 1, в том числе другие ветвления
}
else if (a==2)
{
//несколько десятков операторов 2, в том числе другие ветвления
}
else if (a==3)
{
//несколько десятков операторов 3, в том числе другие ветвления
}
...
и так листа на три, к тому же нет ни одного символа табуляции для иерархии.
Возникает закономерный вопрос (прошу простить меня цензуру): "What a fuck?", неужели нельзя было использовать switch?!
Посидел, покавырялся, распичатал это чудо и теперь сижу и матюгаю автора!
Почитал отдельные отечественные форумы, где люди спрашивают: "Что лучше - switch или гора if'ов?", на которых ответы разнятся, но все же преимущество за switch. Набрал в Google поисковую строку: "Switch vs If" и получил целую гору ссылок, где сравниваются указанные операторы (ссылка 1, ссылка 2) и явное преимущество по скорости работы имеет switch - так на кой черт тогда люди используют гору if'ов, она не только ни быстрее, но еще и читать ее невозможно?
Кто что думает по этому вопросу? Кто что сам использует?
Если кому интересно, то иерархии из if-else в своем коде строю с максимальной глубиной приблизительно равной 3, если нужно больше, то тогда только switch.
Из всех классических книг, посвященных программированию, ненавижу всего одну - русский перевод книги Роберта Седжвика-"Фундаментальные алгоритмы C++". Предпочитаю читать её в оригинале.

Последний раз редактировалось Mixim; 19.02.2013 в 12:01.
Mixim вне форума Ответить с цитированием
Старый 19.02.2013, 12:16   #2
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Цитата:
Кто что сам использует?
Я используй только IF. Во-первых он удобнее аналогичного свича универсальностью, а во вторых моя схема такая:
Код:
if (a==1) proc1(); else 
if (a==2) proc2(); else 
if (a==3) proc3(); else
...
И все такие блоки упаковываю в подпрограммы. Код читабельнее и отлаживать его удобнее.
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 19.02.2013, 12:24   #3
Abstraction
Старожил
 
Аватар для Abstraction
 
Регистрация: 25.10.2011
Сообщений: 3,178
По умолчанию

Цитата:
явное преимущество по скорости работы имеет switch
Закон Парето: 80% времени выполняется 20% кода, так что нефиг экономить на спичках до профилирования. switch ограничен по типам и условиям, так что его использование не всегда более удобочитаемо.

И вообще, несколько десятков операторов с ветвлениями, с разной логикой при разных a - типичное показание к тому, что данный метод должен заниматься только диспетчеризацией. Кстати, если значения идут (почти) подряд, можно обойтись без явных ветвлений:
Код:
public delegate void Variant();

static void IncorrectVariant(){/*...*/}
static void Variant1(){/*...*/}
static void Variant2(){/*...*/}
//...

static Variant[] DispatchVariants = new Variant[] {
  new Variant(IncorrectVariant),
  new Variant(Variant1),
  new Variant(Variant2),
  //...
}

void DispatchByAValue(int a){
  if(a<0 || a>=DispatchVariants.Length){
    IncorrectVariant();
    return; //Можно без этой ветки, если IndexOutOfBoundsException устраивает
  }
  DispatchVariants[a]();
}
Abstraction вне форума Ответить с цитированием
Старый 19.02.2013, 12:39   #4
alezha
Форумчанин
 
Регистрация: 16.04.2011
Сообщений: 126
По умолчанию

я бы использовал switch.
Хотя на каждую ситуацию по разному. Если ты используешь потоки и обращаешься к одной и той же информации в разных потоках (а ведь данные могут меняться), то могут сработать два if или больше.
+ время выполнения гораздо важнее!
alezha вне форума Ответить с цитированием
Старый 19.02.2013, 12:48   #5
Abstraction
Старожил
 
Аватар для Abstraction
 
Регистрация: 25.10.2011
Сообщений: 3,178
По умолчанию

Цитата:
Если ты используешь потоки и обращаешься к одной и той же информации в разных потоках (а ведь данные могут меняться), то могут сработать два if или больше.
Если не изменяет память, switch в таких условиях тоже не даёт особых гарантий. Если код должен быть потокобезопасным, его надо делать таковым отдельными мерами.
Abstraction вне форума Ответить с цитированием
Старый 19.02.2013, 14:05   #6
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Цитата:
то могут сработать два if или больше.
А такого эффекта и без IF можно достичь. Это решается синхронизацией.
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 19.02.2013, 22:54   #7
Демон
Пользователь
 
Регистрация: 12.11.2008
Сообщений: 17
Стрелка

Лично мое мнение, что switch, как оператор выбора, понятнее смотрится в коде, нежели if, оператор условия.
Для перечислений, целых - всегда его юзаю.
Другое дело - производительность. Не стоит искать тестов и сравнений, они все синтетические. Да и ощутимого выигрыша вы не добьетесь, особенно если приложение особо ничем не ворочает. Не занимайтесь преждевременными микрооптимизациями, вам за это не платят только время потеряете.
Навскидку схожий функционал можно получить if-ами, switch-ом, Dictionary, наследованием с переопределением методов, перегрузкой методов (если аргументы разного типа, имеющие общий базовый класс), паттерном состояние/конечным автоматом, и тд. Каждый будет иметь свои выигрыши в разных ситуациях, в т.ч. и производительности.

Ну а к топику - это скорее вопрос стиля, я бы, конечно, использовал в данном случае оператор выбора switch, так как он здесь и подразумевается.
Демон вне форума Ответить с цитированием
Старый 20.02.2013, 02:26   #8
Mixim
Форумчанин
 
Регистрация: 29.10.2009
Сообщений: 259
По умолчанию

Цитата:
Сообщение от Stilet Посмотреть сообщение
Я используй только IF. Во-первых он удобнее аналогичного свича универсальностью, а во вторых моя схема такая:
Код:
if (a==1) proc1(); else 
if (a==2) proc2(); else 
if (a==3) proc3(); else
...
И все такие блоки упаковываю в подпрограммы. Код читабельнее и отлаживать его удобнее.
Нет, я согласен, что иногда удобнее if-else, например когда код пишешь пошагово, т.е. написал пару if-else, запустил в отладчике, проверил, написал еще несколько if-else, снова проверил и т.д., но потом с наскока такой код читать - не самое большое удовольствие!
А универсальность вообще какая? Имеете ввиду, что можно написать следующее:
Код:
if(a==1)
{
}
else
if(a==2)
{
}
else
if(b==1)
{
}
//etc.
? Но IMHO, при таком варианте ни проще ли обернуть условия if-else для каждого оператора в отдельный метод и использовать конструкцию соответствующего вида? Например,
Код:
protected Boolean MethodForA(Int32 A)
{
switch(A)
{
case(1):
{
//...
break;
}
case(2):
{
//...
break;
}
default:
{
return false;
}
}
return true;
}
//end of MethodA

protected Boolean MethodForB(Int32 B)
{
switch(B)
{
case(1):
{
//...
break;
}
case(2):
{
//...
break;
}
default:
{
return false;
}
}
return true;
}
//end of MethodB

public void MainMethod(Int32 A, Int32 B)
{
if(MethodForA(A)!=true)
{
if(MethodForB(B)!=true)
{
//other method
}
}
}
Да, в последнем методе не удалось избавиться от нескольких if-else, но применение switch здесь является не правомерным. Согласитесь, что код более читабелен.
Из всех классических книг, посвященных программированию, ненавижу всего одну - русский перевод книги Роберта Седжвика-"Фундаментальные алгоритмы C++". Предпочитаю читать её в оригинале.
Mixim вне форума Ответить с цитированием
Старый 20.02.2013, 09:34   #9
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Цитата:
А универсальность вообще какая?
В одном IF может быть несколько разнотипных условий )
Вот тебе и универсальность.
Цитата:
Согласитесь, что код более читабелен.
Не согласен. Отсутствие отступов пагубно влияет на код.
Цитата:
ни проще ли обернуть условия if-else для каждого оператора в отдельный метод
Если мне нужно сравнить в одном условии скажем 20 разнотипных переменных, типы которых уникальны для этого условия и не повторяются, я что должен 20 методов описывать? Не слишком ли это расточительно? И писать долго. Букафф больше
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 20.02.2013, 11:07   #10
Abstraction
Старожил
 
Аватар для Abstraction
 
Регистрация: 25.10.2011
Сообщений: 3,178
По умолчанию

Цитата:
Если мне нужно сравнить в одном условии скажем 20 разнотипных переменных, типы которых уникальны для этого условия и не повторяются, я что должен 20 методов описывать?
ИМХО, в этом случае надо крепко задуматься о том, как такой крокодил получился и как от него как можно скорее избавиться. 20 бинарных условий - это миллион логических путей. Многовато для одной точки в коде.
Abstraction вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
switch MasterSporta Общие вопросы C/C++ 4 05.04.2012 22:05
Switch в C++ Inv1s Visual C++ 2 28.01.2012 14:37
C# switch Sna1L Помощь студентам 2 07.07.2011 15:00
switch Артэс Общие вопросы C/C++ 40 29.05.2010 20:11
switch Dimarik Общие вопросы C/C++ 4 11.04.2010 15:56