Często, gdy słyszę o instrukcji switch, jest ona odkładana jako sposób na zastąpienie długich, jeśli ... jeszcze łańcuchów. Ale wydaje się, że kiedy używam instrukcji switch, piszę więcej kodu, który napisałbym, gdyby ... inaczej. Masz również inne problemy, takie jak utrzymywanie wszystkich zmiennych dla wszystkich połączeń w tym samym zakresie .
Oto kod reprezentujący przepływ, który zwykle piszę ( dzięki diam )
String comment; // The generated insult.
int which = (int)(Math.random() * 3); // Result is 0, 1, or 2.
if (which == 0) {
comment = "You look so much better than usual.";
} else if (which == 1) {
comment = "Your work is up to its usual standards.";
} else if (which == 2) {
comment = "You're quite competent for so little experience.";
} else {
comment = "Oops -- something is wrong with this code.";
}
Potem chcą, żebym to zastąpił:
String comment; // The generated insult.
int which = (int)(Math.random() * 3); // Result is 0, 1, or 2.
switch (which) {
case 0:
comment = "You look so much better than usual.";
break;
case 1:
comment = "Your work is up to its usual standards.";
break;
case 2:
comment = "You're quite competent for so little experience.";
break;
default:
comment = "Oops -- something is wrong with this code.";
}
Wydaje się, że jest o wiele więcej kodu w znacznie bardziej niezręcznej składni. Ale czy naprawdę jest korzyść z używania instrukcji switch?
Odpowiedzi:
Dla tej szczególnej sytuacji, wydaje mi się, że oba
if
icase
są biedne wybory. Użyłbym prostej tablicy:Na marginesie, powinieneś ogólnie obliczyć mnożnik w oparciu o rozmiar tablicy, a nie kodować na stałe
3
.Co do kiedy będzie używać przypadek / wyłącznik, różnica z kaskadą
if
sprawozdania (lub przynajmniej jedna zasadnicza różnica) jest to, żeswitch
można półautomatycznie Optymalizacja na podstawie liczby i gęstości wartości, natomiast kaskadąif
sprawozdania liści kompilator z niewielkim wyborem, ale do wygenerowania kodu tak, jak go napisałeś, testowania jednej wartości po drugiej, aż znajdzie dopasowanie. Tylko w trzech rzeczywistych przypadkach nie stanowi to problemu, ale przy wystarczającej liczbie może / może być znaczący.źródło
case
oświadczenia lub kaskadęif
sprawozdania odpowiedni. Przez większość czasu są one (przeciętne) substytutem jakiegoś rodzaju mapy / tablicy, a lepiej jest użyć jednego z nich bezpośrednio.static const
tablicę, aby upewnić się, że zawsze istnieje (ale nie podano żadnego języka w pytaniu, więc starałem się nie zakładać żadnego z nich w odpowiedzi ).Problem z
if...else if...
łańcuchem polega na tym, że kiedy przychodzę go czytać, muszę patrzeć na każdy pojedynczyif
warunek, aby zrozumieć, co robi program. Na przykład możesz mieć coś takiego:(oczywiście dla niewielkiej liczby takich stwierdzeń nie jest tak źle)
Nie miałbym pojęcia, że zmieniłeś zmienną warunkową w połowie bez przeczytania każdej instrukcji. Ponieważ jednak
switch
ogranicza Cię tylko do jednej zmiennej warunkowej, na pierwszy rzut oka widzę, co się dzieje.Jednak pod koniec dnia wolałbym ani
switch
jednego, ani jednego łańcuchaif...else if
. Często lepszym rozwiązaniem jest jakaś tabela skoków lub słownik dla przypadków takich jak w pierwotnym pytaniu lub polimorfizm (jeśli twój język to obsługuje). Oczywiście nie zawsze jest to możliwe, ale szukałem rozwiązania, którego unika sięswitch
jako pierwszy krok ...źródło
Powyższy sposób pisania tego typu skrzynki jest dość powszechny. Powodem, dla którego poczułeś skrzynkę przełącznika, jeśli jest ona nieporęczna, jest to, że twoje ciało było tylko jedną linią, a przy skrzynce przełącznika potrzebujesz również instrukcji break. Zatem obudowa przełącznika miała dwa razy większy rozmiar ciała niż w innym przypadku. W przypadku bardziej znaczącego kodu instrukcja break nie doda wiele do treści. W przypadku treści jednowierszowych powszechną praktyką jest pisanie kodu w tym samym wierszu co instrukcja case.
Jak już wspomnieli inni, przypadek przełącznika sprawia, że intencja jest bardziej wyraźna, chcesz podjąć decyzję na podstawie wartości pojedynczej zmiennej / wyrażenia. Moje komentarze są wyłącznie z punktu widzenia czytelności i nie są oparte na wydajności.
źródło
return
ma odpowiedni ciąg, możesz wyeliminowaćbreak
instrukcje.W takim przypadku instrukcja switch bardziej pasuje do intencji kodu: wybierz akcję, która ma zostać podjęta na podstawie pojedynczej wartości.
Z drugiej strony zdania if są znacznie trudniejsze do odczytania - musisz spojrzeć na wszystkie, aby się upewnić, co się dzieje. Dla mnie jest to mniej kodu (nawet jeśli liczba znaków może być nieco wyższa), ponieważ jest mniej do przeanalizowania w myślach.
źródło
Zgadzam się z Jerrym, że tablica ciągów jest lepsza w tym konkretnym przypadku, ale ogólnie lepiej jest użyć instrukcji switch / case niż łańcucha elseifs. Jest łatwiejszy do odczytania, a czasem kompilator może lepiej zoptymalizować w ten sposób, ale jest też jeszcze jedna korzyść: jest o wiele łatwiejszy do debugowania.
Kiedy naciśniesz ten przełącznik, musisz tylko raz przejść do właściwej gałęzi, zamiast ostrożnie przeskakiwać kilka instrukcji if pojedynczo, i być może zbyt szybko uderzać w klawisz, przechodzić obok niego i coś pominąć i mieć Rozpocząć od nowa.
źródło
Wolę zamianę w tego rodzaju przypadkach, znacznie lepiej pasuje do kodu, wykonaj inną instrukcję dla każdej innej wartości wejściowej.
if..else
Działa bardziej jak „trick”, aby osiągnąć ten sam efekt.switch
instrukcje są również czystsze, łatwo jest w nich ukryć literówkę==
Ponadto w przypadku dużych bloków w C przełączanie jest szybsze.
else..if
może być bardziej odpowiednie, gdy masz coś w rodzaju zakresów (od 1 do 100, zrób to, od 100 do 200, zrób to) lub w C, gdy próbujesz dokonać przełączenia z elementami takimi jak łańcuchy (jest to możliwe w innych językach). Który jest taki sam.Zwykle używam wielu przełączników, gdy programuję w C.
źródło
Wybierz coś wydajnego, zwięzłego, a następnie udokumentuj nie tylko to, co zrobiłeś, ale dlaczego.
Kod może zostać zmieniony i nie zawsze przez jego oryginalnego autora.
Są chwile, kiedy możesz celowo wybrać jedną implementację zamiast drugiej, ponieważ myślisz o kodzie, który nie istnieje.
źródło
Generalnie nie lubię żadnego z tych podejść. Długi przełącznik lub jeśli instrukcje dopiero zaczynają być przekształcane w abstrakcję zorientowaną obiektowo (jednak twój przykład sklasyfikowałbym jako krótki, a nie długi).
Osobiście owinąłbym ten rodzaj kodu osobną metodą pomocniczą.
Umieszczenie przełącznika w osobnej metodzie umożliwia umieszczenie instrukcji return bezpośrednio wewnątrz instrukcji switch (przynajmniej w c #), eliminując również potrzebę instrukcji break, co znacznie ułatwia odczytanie kodu.
I to jest o wiele ładniejsze niż podejście if / else if / else if.
źródło
W Pythonie nie ma instrukcji switch, ponieważ jeśli / elif / else jest miły:
Proste prawda?
źródło
Elif
to tylko instrukcja if z kilkoma brakującymi literami. To zdecydowanie bardziej przypominaif
instrukcję niż instrukcję switch. Fakt, że Python NIE ma przełącznika, sprawia, że ktoś, kto ich nienawidzi (jak ja), myśli, że nie są sami.meta
chyba że jest to znany temat. Dzięki, że dałeś mi świadka.Jedną z rzeczy, która sprawia, że styl C / C # jest
switch
szczególnie denerwujący, jest nacisk nacase
wartość, która jest dosłowna. Jedną fajną rzeczą w VB / VB.NET jest to, żeselect/case
każdy przypadek może być dowolnym wyrażeniem logicznym. To jest wygodne. O ile seria wzajemnie wykluczających się wyrażeń boolowskich jest często pomocna, seria if / else ifs jest bardziej elastyczna, nie wspominając już o bardziej wydajnym pisaniu i czytaniu.źródło