Odkąd pamiętam, unikałem używania instrukcji switch fall-through. Właściwie nie pamiętam, żeby kiedykolwiek wkroczyło do mojej świadomości jako możliwy sposób robienia rzeczy, ponieważ wcześnie wwiercono mi się w głowę, że to nic innego jak błąd w instrukcji przełącznika. Jednak dzisiaj natknąłem się na kod, który używa go zgodnie z projektem, co sprawiło, że od razu zacząłem się zastanawiać, co wszyscy w społeczności myślą o upadku instrukcji switch.
Czy jest to coś, na co język programowania nie powinien wyraźnie zezwalać (tak jak robi to C #, chociaż dostarcza obejścia), czy też jest to cecha dowolnego języka, która jest wystarczająco potężna, aby pozostawić ją w rękach programisty?
Edycja: Nie byłem wystarczająco szczegółowy, co miałem na myśli, mówiąc o upadku. Często używam tego typu:
switch(m_loadAnimSubCt){
case 0:
case 1:
// Do something
break;
case 2:
case 3:
case 4:
// Do something
break;
}
Martwię się jednak o coś takiego.
switch(m_loadAnimSubCt){
case 0:
case 1:
// Do something, but fall through to the other cases
// after doing it.
case 2:
case 3:
case 4:
// Do something else.
break;
}
W ten sposób za każdym razem, gdy wielkość liter wynosi 0, 1, zrobi wszystko w instrukcji switch. Widziałem to zgodnie z projektem i po prostu nie wiem, czy zgadzam się, że instrukcje przełączające powinny być używane w ten sposób. Myślę, że pierwszy przykład kodu jest bardzo przydatny i bezpieczny. Drugi wydaje się trochę niebezpieczny.
źródło
Odpowiedzi:
Może to zależeć od tego, co uważasz za przełomowe. Nie przeszkadza mi tego typu rzeczy:
Ale jeśli masz etykietę przypadku, po której następuje kod, który przechodzi do innej etykiety przypadku, prawie zawsze uważałbym to za zło. Być może lepszym pomysłem byłoby przeniesienie wspólnego kodu do funkcji i wywołanie z obu miejsc.
Pamiętaj, że używam definicji „zła” w C ++ FAQ
źródło
To miecz obosieczny. Czasami jest to bardzo przydatne, ale często niebezpieczne.
Kiedy jest dobrze? Jeśli chcesz, aby 10 przypadków było przetwarzanych w ten sam sposób ...
Jedyną zasadą, która mi się podoba, jest to, że jeśli kiedykolwiek zrobisz coś wymyślnego i wykluczysz przerwę, potrzebujesz wyraźnego komentarza / * FALLTHROUGH * /, aby wskazać, że był to twój zamiar.
źródło
if(condition > 1 && condition <10) {condition = 1}; switch(...
zapisać przypadki (dla wyraźnego spojrzenia), a każdy może zobaczyć, że naprawdę chciałeś, aby te przypadki wyzwoliły tę samą akcję.Czy słyszałeś o urządzeniu Duffa ? To świetny przykład wykorzystania przełącznika Fallthrough.
Jest to funkcja, której można używać i można ją nadużywać, podobnie jak prawie wszystkie funkcje języka.
źródło
Opadanie jest naprawdę poręczne, w zależności od tego, co robisz. Rozważ ten schludny i zrozumiały sposób aranżacji opcji:
Wyobraź sobie, że robisz to z if / else. To byłby bałagan.
źródło
Może to być bardzo przydatne kilka razy, ale ogólnie rzecz biorąc, brak awarii jest pożądanym zachowaniem. Przechodzenie powinno być dozwolone, ale nie dorozumiane.
Przykład aktualizacji starych wersji niektórych danych:
źródło
Chciałbym mieć inną składnię dla awaryjnych przełączników, coś w rodzaju, błąd ...
Uwaga: byłoby to już możliwe w przypadku wyliczeń, jeśli zadeklarujesz wszystkie przypadki w swoim wyliczeniu za pomocą flag, prawda? To też nie brzmi tak źle; Sprawy mogłyby (powinny?) już być częścią twojego wyliczenia.
Może byłby to fajny przypadek (bez gry słów) dla płynnego interfejsu z metodami rozszerzającymi? Coś jak, błąd ...
Chociaż to chyba jeszcze mniej czytelne: P
źródło
Jak wszystko: jeśli jest używany ostrożnie, może być eleganckim narzędziem.
Uważam jednak, że wady bardziej niż usprawiedliwiają, aby go nie używać, a ostatecznie nie pozwalać już na to (C #). Wśród problemów są:
Dobre wykorzystanie przełącznika / obudowy:
Baaaaad użycie przełącznika / przełamania obudowy:
Można to przepisać przy użyciu konstrukcji if / else bez żadnych strat, moim zdaniem.
Moje ostatnie słowo: trzymaj się z daleka od błędnych etykiet przypadków, jak w złym przykładzie, chyba że zachowujesz starszy kod, w którym ten styl jest używany i dobrze rozumiany.
źródło
Jest potężny i niebezpieczny. Największym problemem związanym z przebiciem jest to, że nie jest on wyraźny. Na przykład, jeśli napotkasz często edytowany kod, który ma przełącznik z błędami, skąd wiesz, że jest to zamierzone, a nie błąd?
Gdziekolwiek go używam, zapewniam, że jest odpowiednio skomentowany:
źródło
Korzystanie z przejścia tak jak w pierwszym przykładzie jest oczywiście w porządku i nie uważałbym tego za prawdziwy upadek.
Drugi przykład jest niebezpieczny i (jeśli nie jest szeroko komentowany) nieoczywisty. Uczę moich uczniów, aby nie używali takich konstrukcji, chyba że że uznają, że warto poświęcić im blok komentarza, który opisuje, że jest to celowa wpadka i dlaczego to rozwiązanie jest lepsze niż alternatywy. To zniechęca do niechlujnego używania, ale nadal sprawia, że jest to dozwolone w przypadkach, gdy jest wykorzystywane na korzyść.
Jest to mniej więcej równoważne temu, co robiliśmy w projektach kosmicznych, gdy ktoś chciał złamać standard kodowania: musiał ubiegać się o zwolnienie (a mnie wezwano, aby doradzić w sprawie wyroku).
źródło
Nie podoba mi się, że moje
switch
oświadczenia upadają - są zbyt podatne na błędy i trudne do odczytania. Jedynym wyjątkiem jest sytuacja, gdy wielecase
instrukcji działa dokładnie to samo.Jeśli istnieje jakiś wspólny kod, którego chce użyć wiele gałęzi instrukcji switch, wyodrębniam go do oddzielnej wspólnej funkcji, którą można wywołać w dowolnej gałęzi.
źródło
W niektórych przypadkach używanie fall-through jest aktem lenistwa ze strony programisty - przydałoby mu się seria || na przykład instrukcje, ale zamiast tego używają serii przypadków przełączania typu „catch-all”.
Biorąc to pod uwagę, stwierdziłem, że są one szczególnie pomocne, gdy wiem, że ostatecznie i tak będę potrzebować opcji (na przykład w odpowiedzi menu), ale nie zaimplementowałem jeszcze wszystkich opcji. Podobnie, jeśli robisz upadek zarówno dla „a”, jak i „A”, uważam, że znacznie czystszym jest użycie przełącznika przelotowego niż złożonej instrukcji if.
Prawdopodobnie jest to kwestia stylu i tego, jak myślą programiści, ale generalnie nie przepadam za usuwaniem składników języka w imię `` bezpieczeństwa '' - dlatego bardziej skłaniam się ku C i jego wariantom / potomkom niż, powiedzmy, Jawa. Lubię być w stanie małpować ze wskazówkami i tym podobnymi, nawet jeśli nie mam do tego „powodu”.
źródło
Fall-through powinno być używane tylko wtedy, gdy jest używane jako tablica skoków do bloku kodu. Jeśli jakakolwiek część kodu zawiera bezwarunkową przerwę przed większą liczbą przypadków, wszystkie grupy przypadków powinny kończyć się w ten sposób.
Wszystko inne jest „złe”.
źródło