Перерва на випадок за замовчуванням в комутаторі


88

Мене трохи спантеличує всякий раз, коли я не включаюсь breakпісля останнього випадку, часто default.

switch (type) {
    case 'product':

        // Do behavior

        break;
    default:

        // Do default behavior

        break; // Is it considered to be needed?
}

breaks єдина мета, наскільки я розумію, не допустити проходження коду через іншу частину switch-case.

Тоді чи вважається більш логічним мати breakостанній через послідовність або пропустити його через breakвідсутність функціонального використання? На мою думку, обидва є логічними по-різному.

Це можна певною мірою порівняти із закінченням .phpфайлу ?>. Я ніколи не закінчуюсь ?>здебільшого через ризик виведення порожніх пробілів, але можна стверджувати, що було б логічно закінчити файл.

Відповіді:


144

breakтехнічно не потрібна після останньої альтернативи (що, зауважте, не повинно бути default: цілком законно, а іноді навіть корисно ставити defaultгілку на перше місце); Незалежно від того, чи буде ваш код потрапляти в кінець switchзаяви або breaksв кінці останньої гілки, такий же результат.

Однак я все-таки закінчував би кожну гілку, включаючи останню, з returnабо breakзаявою з трьох причин:

  1. Повторність дії. Якщо всі ваші гілки закінчуються breakабо return, ви можете змінити їх порядок, не змінюючи значення. Це робить меншою ймовірність такого переназначення ввести регресію.
  2. Послідовність і найменший сюрприз. Послідовність каже, що ваші гілки повинні закінчуватися послідовно, якщо вони насправді не відрізняються за значенням. Принцип найменшого сюрпризу диктує, що подібні речі повинні виглядати схоже. Закінчення останньої гілки switchблоку точно так само, як і попереднє, виконує обоє, що полегшує читання та розуміння. Якщо ви не залишите явне break, остання гілка буде оптично іншою (що особливо важливо для швидкого сканування), і для того, щоб переконатися, що вона насправді не відрізняється, читачеві доведеться опуститися до рівня неглибокого читання окремих тверджень .
  3. Захист себе. Якщо ви звикли закінчувати всі ваші switchгілки символом break, воно через деякий час стане автоматичним, і ви будете менше шансів випадково забути його там, де це має значення. Навчання себе, щоб очікувати breakв кінці кожної гілки, також допомагає виявити відсутні дані break, що чудово підходить для налагодження та усунення несправностей.

Дякуємо за ваше розуміння в цьому! breakВостаннє справа буде так само :)
Робін Кастлін

7
У C #, break(або іншого заяві потоку управління , який виходить з case) є технічно необхідно після останньої альтернативи.
dan04

3
@ dan04: так, хороший момент. C # - тут виняток, і це, мабуть, тому, що мовні дизайнери знали про проблеми з switchпроникненням у існуючі мови та хотіли їх запобігти. Правила C # накладають в значній мірі відповідні рекомендаціям моєї відповіді.
tdammers

Якою мовою ви конкретно говорите? C? C ++? C #? Java? PHP?
svick

2
Хороший компілятор розглядав би фінал breakяк NO-OP замість того, щоб генерувати jmpнаступну інструкцію, правильно?
Натан Осман

11

З огляду на неоднозначність, яка існує навколо використання switch-caseбільшості мов, при його використанні я б пропонував завжди використовувати breakоператор, за винятком випадків, коли це явно і за конструкцією не хочеться .

Частково це відбувається через те, що робить кожен caseвиклик однаковим, що, на мою думку, покращило б читаність. Але це також означає, що якщо хтось (навіть ви) вирішує вставити caseпісля останнього на більш пізньому етапі, їм не потрібно перейматися перевіркою попереднього блоку, що може допомогти зменшити помилки при додаванні нового коду.


7
Коли я хочу, щоб один випадок перейшов на інший (а це не вироджений випадок case foo: case bar: ...), я вказую чіткий коментар у тому, що хочу, щоб провал стався. Це робить набагато зрозумілішим.
Дональні стипендіати

3
Так, як простий коментар // no breakзамістьbreak;
Pacerier

Або [[fallthrough]]атрибут у випадку C ++.
Руслан

1

Немає breakнеобхідності після останнього випадку. Я використовую слово " останнє " (не за замовчуванням ), оскільки це не обов'язково, за замовчуванням це останній випадок.

switch(x)
{
case 1:
//do stuff
break;

default:
//do default work
break;

case 3:
//do stuff

}

І ми знаємо, що break необхідно між двома послідовними caseс. Іноді я використовую if(a!=0)в своєму коді для більшої читабельності, коли інші посилаються на мій код. Я можу вибрати if(a), що використовувати , це було б питанням мого вибору


5
Для мене це означатиме "завжди використовувати перерву", на всякий випадок, коли якийсь програміст додав нове caseв кінці вашого, switchне перевіряючи, чи breakдійсно існує (це було б виною цього програміста, але все ж краще бути безпечним - якщо з будь-якої причини, тому що ви могли бути цим програмістом через 6 місяців-)
SJuan76,

@ SJuan76 Так, я згоден, краще безпечно, ніж вибачте, якщо ви хочете зберегти захист від майбутніх помилок, ви повинні включити його в кінці.
Suvarna Pattayil

1
Маючи на увазі цей аргумент, ви можете також стверджувати, що завжди є , в кінці масивів, якщо введено нове значення. Однак це порушує деякі коди і, як правило, виглядає некрасиво :)
Робін Кастлін

1
@Robin Введення коми відрізняється. Якщо його немає, і хтось додасть нове значення до масиву, тоді вони отримають помилку компіляції. Однак помилки компіляції не буде, якщо в попередньому викладі справи відсутній перерва - тому це може бути пропущено і викликати помилки під час виконання.
Кіт Міллер

@RobinCastlin За умови, що мова дозволила вам поставити ,. Incase, defaultбув розроблений як останній випадок. Можливо, мова вважатиме breakпісля нього помилкою. Припущення breakбуло дозволено як диференціатор ТІЛЬКИ між двома випадками.
Suvarna Pattayil
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.