Przerwij domyślną wielkość liter w przełączniku

88

breakCzęsto zastanawiam się nad tym, czy mogę to uwzględnić po ostatnim przypadku default.

switch (type) {
    case 'product':

        // Do behavior

        break;
    default:

        // Do default behavior

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

breakmoim jedynym celem jest zatrzymanie uruchamiania kodu przez resztę switchskrzynki.

Czy zatem uważa się za bardziej logiczne, aby mieć breakostatnią ze względu na spójność lub pominąć ją ze względu na breakbrak zastosowania funkcjonalnego? Oba są moim zdaniem logiczne na różne sposoby.

Można to do pewnego stopnia porównać z zakończeniem .phppliku ?>. Nigdy nie kończę, ?>głównie ze względu na ryzyko generowania pustych miejsc, ale można argumentować, że logicznym rozwiązaniem byłoby zakończenie pliku.

Robin Castlin
źródło

Odpowiedzi:

144

breaknie jest technicznie potrzebny po ostatniej alternatywie (która, defaultniestety , wcale nie musi być : jest całkowicie legalna, a czasem nawet przydatna, aby umieścić defaultgałąź na pierwszym miejscu); to, czy kod wypadnie na końcu switchinstrukcji, czy breaksna końcu ostatniej gałęzi, ma ten sam wynik.

Jednak nadal kończę każdą gałąź, w tym ostatnią, instrukcją returnlub breakz trzech powodów:

  1. Refaktowalność. Jeśli wszystkie gałęzie kończą się na breaklub return, możesz zmienić ich kolejność bez zmiany znaczenia. To sprawia, że ​​mniej prawdopodobne jest, aby taka zmiana kolejności wprowadziła regresję.
  2. Spójność i najmniejsza niespodzianka. Spójność mówi, że twoje gałęzie powinny kończyć się konsekwentnie, chyba że faktycznie mają inne znaczenie. Zasada najmniejszej niespodzianki mówi, że podobne rzeczy powinny wyglądać podobnie. Zakończenie ostatniej gałęzi switchbloku dokładnie tak, jak poprzednie spełnia oba, co ułatwia czytanie i zrozumienie. Jeśli pominiesz wyraźne break, ostatnia gałąź będzie optycznie inna (co jest szczególnie ważne w przypadku szybkiego skanowania), a aby zobaczyć, że tak naprawdę nie jest inaczej, czytelnik musi zejść do drobiazgowego poziomu czytania poszczególnych instrukcji .
  3. Chronić siebie. Jeśli przyzwyczaisz się kończyć wszystkie swoje switchgałęzie break, po pewnym czasie stanie się ono automatyczne i rzadziej przypadkowo zapomnisz, gdzie to ma znaczenie. Przygotowanie się do oczekiwania breakna końcu każdej gałęzi pomaga również w wykrywaniu brakujących breakinstrukcji, co doskonale nadaje się do debugowania i rozwiązywania problemów.
tdammers
źródło
Dziękujemy za wgląd w to! Będzie breakostatnia sprawa również :)
Robin Castlin
7
W języku C # break(lub inna instrukcja sterowania przepływem, która wychodzi z case) jest technicznie potrzebna po ostatniej alternatywie.
dan04
3
@ dan04: tak, dobra uwaga. C # jest tutaj wyjątkiem i prawdopodobnie dlatego, że projektanci języków wiedzieli o problemach z switchprzechodzeniem w istniejących językach i chcieli im zapobiec. Reguły C # narzucają się w zasadzie z zaleceniami z mojej odpowiedzi.
tdammers
O jakim języku mówisz konkretnie? DO? C ++? DO#? Jawa? PHP?
svick,
2
Dobry kompilator traktuje finał breakjako NO-OP zamiast generować jmpinstrukcję do następnej instrukcji, prawda?
Nathan Osman
11

Biorąc pod uwagę niejednoznaczność, jaka istnieje wokół używania switch-casew większości języków, podczas korzystania z niego sugerowałbym, aby zawsze używać breakoświadczenia, z wyjątkiem przypadków, gdy jest to wyraźnie i z założenia niepożądane .

Częściowo dzieje się tak, ponieważ sprawia, że ​​każde casepołączenie wygląda tak samo, co moim zdaniem poprawiłoby czytelność. Ale oznacza to również, że jeśli ktoś (nawet ty) zdecyduje się wstawić casepo ostatnim na późniejszym etapie, nie musi zajmować się sprawdzaniem poprzedniego bloku, co może pomóc w zmniejszeniu błędów podczas dodawania nowego kodu.


źródło
7
Kiedy chcę, aby jedna sprawa przeszła do następnej (a nie jest to przypadek zdegenerowany case foo: case bar: ...), umieszczam wyraźny komentarz, że chcę, aby nastąpiła awaria. Sprawia, że ​​jest to wyraźniejsze.
Donal Fellows
3
Tak, jak zwykły komentarz // no breakzamiastbreak;
Pacerier,
Lub [[fallthrough]]atrybut w przypadku C ++.
Ruslan
1

breakPo ostatnim przypadku nie jest konieczne . Używam słowa „ ostatni ” (nie domyślny ), ponieważ nie jest to konieczne, domyślny przypadek to ostatni przypadek.

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

default:
//do default work
break;

case 3:
//do stuff

}

I wiemy, że break konieczne jest a pomiędzy dwoma kolejnymi cases. Czasami używam if(a!=0)w swoim kodzie dla większej czytelności, gdy inni odsyłają mój kod. Mogę wybrać użycie if(a), to byłby mój wybór

Suvarna Pattayil
źródło
5
Dla mnie oznaczałoby to „zawsze używaj przerwy”, na wypadek gdyby jakiś programista dodał nowy casena końcu twojego, switchnie sprawdzając, breakczy on istnieje (byłaby to wina programisty, ale lepiej być bezpiecznym - jeśli z jakiegokolwiek powodu, ponieważ możesz zostać programistą za 6 miesięcy-)
SJuan76,
@ SJuan76 Tak, zgadzam się, lepiej zabezpieczyć niż przepraszać, jeśli chcesz zachować zabezpieczenie na wypadek przyszłych błędów, musisz dołączyć je na końcu.
Suvarna Pattayil
1
Mając to na uwadze, możesz również argumentować, że zawsze masz , na końcu tablic, w przypadku wstawienia nowej wartości. To jednak łamie niektóre kody i ogólnie wygląda brzydko :)
Robin Castlin
1
@ Robin Wprowadzanie przecinka jest inne. Jeśli go nie ma i ktoś doda nową wartość do tablicy, otrzyma błąd kompilacji. Jednak nie wystąpi błąd kompilacji, jeśli poprzednia instrukcja przypadku nie zawiera przerwy - może to być pominięte i spowodować błędy w czasie wykonywania.
Keith Miller,
@RobinCastlin Pod warunkiem, że język pozwala na umieszczenie ,. Incase, defaultzostał zaprojektowany jako ostatni przypadek. Może język uznałby breakgo za błąd. Zakładając, że breakdozwolone było rozróżnienie TYLKO dwóch przypadków.
Suvarna Pattayil