Что лучший способ состоит в том, чтобы заменить или заменить если.. еще, если.. еще деревья в программах?

Да, важно, чтобы ваш элемент использовался как ключ в словаре, или HashSet и т. д. - поскольку он используется (при отсутствии пользовательского IEqualityComparer) для группировки элементов в ведра. Если хэш-код для двух элементов не соответствует, они могут never считаться равными (Equals просто никогда не будет вызываться).

Метод GetHashCode() должен отражать логика Equals; следующие правила:

  • , если две вещи равны (Equals(...) == true), то они должны возвращать одно и то же значение для GetHashCode()
  • , если GetHashCode() равен, для них необходимо не , чтобы они были одинаковыми; это столкновение, и Equals будет вызываться, чтобы убедиться, что это реальное равенство.

В этом случае это выглядит так: «return FooId;» является подходящим GetHashCode(). Если вы тестируете несколько свойств, обычно их объединяют с использованием кода, как показано ниже, для уменьшения диагональных столкновений (т. Е. Для new Foo(3,5) имеет другой хеш-код для new Foo(5,3)):

int hash = 13;
hash = (hash * 7) + field1.GetHashCode();
hash = (hash * 7) + field2.GetHashCode();
...
return hash;

Ох - для удобства вы можете также рассмотреть возможность предоставления операторов == и != при переопределении Equals и GetHashCode.


Демонстрация того, что происходит, когда вы ошибаетесь здесь .

34
задан Esko 7 February 2009 в 04:40
поделиться

20 ответов

Эти конструкции могут часто заменяться полиморфизмом. Это даст Вам короче и менее хрупкому коду.

21
ответ дан Brian Rasmussen 24 September 2019 в 06:47
поделиться

Естественно, этот вопрос является языковозависимым, но оператор переключения мог бы быть более оптимальным вариантом во многих случаях. Хороший C или компилятор C++ смогут генерировать таблица переходов , которая будет значительно быстрее для больших наборов случаев.

0
ответ дан jasonmray 24 September 2019 в 06:47
поделиться

Если у Вас действительно должен быть набор того, если бы тесты и хотят сделать, разные вещи whenwver тест верны, что я рекомендовал бы некоторое время цикл только с IFS - нет еще. Каждый, если делает тест вызовы метод затем, убегает из цикла. Нет еще нет ничего худшего, чем набор сложенного if/else/if/else и т.д.

0
ответ дан mP. 24 September 2019 в 06:47
поделиться

Я расцениваю, они если-lseif-... создают как "шум ключевого слова". В то время как может быть ясно, что это делает, этому недостает краткости; я рассматриваю краткость как важную часть удобочитаемости. Большинство языков обеспечивает что-то как switch оператор. Создание карты является способом получить что-то подобное на языках, которые не имеют такого, но, конечно, похоже на обходное решение, и существует немного служебное (оператор переключения переводит в некоторых простых, сравнивают операции и условные переходы, но карта сначала создается в памяти, затем запросила, и только затем сравнивание и переход происходят).

В языке Common LISP, существует две встроенные конструкции переключателя, cond и case. cond позволяет произвольные условные выражения, в то время как case только тесты для равенства, но более кратко.

(cond ((= i 1)
       (do-one))
      ((= i 2)
       (do-two))
      ((= i 3)
       (do-three))
      (t
       (do-none)))

(case i (1 (do-one)) (2 (do-two)) (3 (do-three)) (otherwise (do-none)))

, Конечно, Вы могли сделать свое собственное case - как макрос для Ваших потребностей.

В Perl, можно использовать for оператор, дополнительно с произвольной маркировкой (здесь: SWITCH):

SWITCH: for ($i) {
    /1/ && do { do_one; last SWITCH; };
    /2/ && do { do_two; last SWITCH; };
    /3/ && do { do_three; last SWITCH; };
    do_none; };
1
ответ дан Svante 24 September 2019 в 06:47
поделиться

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

Переключатели имеют недостаток пропавших без вести операторов завершения и проваливаются и действительно поощряют не повреждать проблему в мелкие кусочки.

, Что быть сказанным: маленькое дерево если.. else's прекрасен (на самом деле, я спорил за в течение многих дней о, имеют 3 если.. elses вместо того, чтобы недавно использовать Карту). Когда Вы начинаете помещать более сложную логику в них, что это становится проблемой из-за пригодности для обслуживания и удобочитаемости.

1
ответ дан Richard Levasseur 24 September 2019 в 06:47
поделиться

В Python я написал бы Ваш код как:

actions = {
           1: doOne,
           2: doTwo,
           3: doThree,
          }
actions[i]()
1
ответ дан too much php 24 September 2019 в 06:47
поделиться

Я сказал бы даже, что никакая программа еще никогда не должна использовать. Если Вы делаете Вы напрашиваетесь на неприятности. Вы никогда не должны принимать, не является ли это X, это должен быть Y. Ваши тесты должны протестировать на каждого индивидуально и сбой после таких тестов.

2
ответ дан mghie 24 September 2019 в 06:47
поделиться

switch оператор или классы с виртуальными функциями как необычное решение. Или массив указателей на функции. Это, все зависит от того, как сложные условия, иногда нет никакого пути вокруг тех if's. И снова, создание серии классов для предотвращения одного оператора переключения является явно неправильным, код должен быть максимально простым (но не более простым)

2
ответ дан vava 24 September 2019 в 06:47
поделиться

Я использую следующую стенографию только для забавы! Не пробуйте anyof они, если код clearity касается Вас больше, чем количество введенных символов.

Для случаев, где doX () всегда возвращает true.

i==1 && doOne() || i==2 && doTwo() || i==3 && doThree()

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

можно также обеспечить присвоения.

i==1 && (ret=1) || i==2 && (ret=2) || i==3 && (ret=3)

Как instad записи

if(a==2 && b==3 && c==4){
    doSomething();
else{
    doOtherThings();
}

Запись

a==2 && b==3 && c==4 && doSomething() || doOtherThings();

И в случаях, где не уверенный, что возвратит функция, добавляют || 1 :-)

a==2 && b==3 && c==4 && (doSomething()||1) || doOtherThings();

я все еще нахожу, что он быстрее вводит, чем использование всех их если еще и он верные волнения все новые новички. Вообразите полную страницу оператора как это с 5 уровнями расположения с отступом.

, "если" редко в некоторых моих кодах и я дал ему имя "при программировании" :-)

3
ответ дан CDR 24 September 2019 в 06:47
поделиться

В этом простом случае Вы могли использовать переключатель.

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

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

3
ответ дан starblue 24 September 2019 в 06:47
поделиться

В парадигме OO Вы могли сделать это с помощью старого доброго полиморфизм . Слишком большой, если - еще структуры или конструкции переключателя иногда считают запахом в коде.

1
ответ дан Nazgob 24 September 2019 в 06:47
поделиться
switch (i) {
  case 1:  doOne(); break;
  case 2:  doTwo(); break;
  case 3:  doThree(); break;
  default: doNone(); break;
}

вводивший это, я должен сказать, что нет так много, неправильного с Вашим если оператор. Как сказанный Einstein: "Сделайте его максимально простым, но не более простым".

3
ответ дан Svante 24 September 2019 в 06:47
поделиться

В зависимости от типа вещи Вы то, если.. else'ing, рассмотрите создание иерархии объектов и использования полиморфизма. Как так:

class iBase
{
   virtual void Foo() = 0;
};

class SpecialCase1 : public iBase
{
   void Foo () {do your magic here}
};

class SpecialCase2 : public iBase
{
   void Foo () {do other magic here}
};

Затем в Вашем коде просто называют p->, Foo () и правильная вещь произойдет.

5
ответ дан Steve Rowe 24 September 2019 в 06:47
поделиться

Пример, данный в вопросе, достаточно тривиален для работы с простым переключателем. Проблема возникает, когда если-elses вкладываются глубже и глубже. Они больше не "ясны или легки читать", (как кто-то еще обсужденный) и добавление нового кода или исправление ошибок в них становится все более трудным и более твердым быть уверенным в том, потому что Вы не могли бы закончить, где Вы ожидали, сложна ли логика.

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

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

3
ответ дан Michel 24 September 2019 в 06:47
поделиться

переключатель оператор, конечно, намного более симпатичный затем все они if's и else's.

3
ответ дан colithium 24 September 2019 в 06:47
поделиться

Существует две части к тому вопросу.

, Как для диспетчеризации на основе значения? Используйте оператор переключения. Это отображает Ваше намерение наиболее ясно.

, Когда для диспетчеризации на основе значения? Только в одном месте на значение: создайте полиморфный объект, который знает, как обеспечить ожидаемое поведение для значения.

5
ответ дан 24 September 2019 в 06:47
поделиться

На Объектно-ориентированных языках распространено использовать полиморфизм для замены if's.

мне понравился этот Google Clean Code Talk, который покрывает предмет:

Чистые Переговоры по Коду - Наследование, Полиморфизм, & при Тестировании

КРАТКИЙ ОБЗОР

Является кодом, полным если операторы? Операторы переключения? У Вас есть тот же оператор переключения в различных местах? При внесении изменений, Вы вносите то же изменение в то же если/переключатель в нескольких местах? Вы когда-либо забывали тот?

Этот разговор обсудит подходы к использованию Объектно-ориентированных методов для удаления многих из тех условных выражений. Результатом является более чистый, более трудный, лучший разработанный код, который это легче протестировать, понять и поддержать.

11
ответ дан Toon Krijthe 24 September 2019 в 06:47
поделиться

Оператор переключения:

switch(i)
{
  case 1:
    doOne();
    break;

  case 2:
    doTwo();
    break;

  case 3:
    doThree();
    break;

  default:
    doNone();
    break;
}
11
ответ дан Andrew Kennan 24 September 2019 в 06:47
поделиться

За пределами использования оператора переключения, который может быть быстрее, ни один. Если Еще ясно и легок читать. необходимость искать вещи в карте запутывает вещи. Почему делают код тяжелее для чтения?

3
ответ дан WolfmanDragon 24 September 2019 в 06:47
поделиться

Используйте переключатель/случай, это более чисто :p

3
ответ дан fmsf 27 November 2019 в 16:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: