it-swarm-eu.dev

Měl bych použít příkazy přepínače nebo dlouhé, pokud ... jinde řetězy?

Když slyším o prohlášení o přepnutí, často se to odkládá jako způsob, jak nahradit dlouhé, pokud ... jinak řetězy. Ale zdá se, že když použiji příkaz switch, píšu další kód, který bych jen psal, kdyby ... jinak. Máte také další problémy jako zachování všech proměnných pro všechna volání ve stejném rozsah .

Zde je nějaký kód, který představuje tok, který normálně zapisuji ( díky 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.";
}

Potom chtějí, abych to nahradil tímto:

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.";
}

Vypadá jako mnohem více kódu v mnohem nepříjemnější syntaxi. Existuje však opravdu výhoda použití příkazu switch?

36
TheLQ

Pro tuto konkrétní situaci se mi zdá, že jak if, tak case jsou špatné volby. Použil bych jednoduché pole:

String comments[] = {
    "You look so much better than usual.",
    "Your work is up to its usual standards.",
    "You're quite competent for so little experience."
};

String comment = comments[(int)(Math.random() * 3)];

Jako vedlejší poznámku byste měli obecně spočítat multiplikátor na základě velikosti pole namísto pevného kódování 3.

Pokud použijete použijete případ/přepínač, rozdíl v kaskádě příkazů if (nebo alespoň jeden hlavní rozdíl) je v tom, že switch může polo- se automaticky optimalizuje na základě počtu a hustoty hodnot, zatímco kaskáda příkazů if ponechává kompilátor s malou volbou, ale generovat kód tak, jak jste ho napsali, testování jedné hodnoty za druhou, dokud nenajde shodu. S pouhými třemi skutečnými případy to není problém, ale s dostatečným počtem to může/mohlo být významné.

57
Jerry Coffin

Problém s řetězcem if...else if... Spočívá v tom, že když si ho přečtu, musím se podívat na každou podmínku if, abych pochopil, co program dělá. Můžete mít například něco podobného:

if (a == 1) {
    // stuff
} else if (a == 2) {
    // stuff
} else if (a == 3) {
    // stuff
} else if (b == 1) {
    // stuff
} else if (b == 2) {
    // stuff
}

(samozřejmě u malého počtu takových tvrzení to není tak špatné)

Nedokázal bych vědět, že jste proměnnou proměnných podmínek v polovině cesty změnili, aniž byste si přečetli každý jednotlivý výrok. Protože vás však proměnná switch omezuje pouze na jednu proměnnou podmínky, vidím na první pohled, co se děje.

Na konci dne bych však raději ani switch ani řetězec if...else if. Lepším řešením je často nějaký skokový stůl nebo slovník pro případy jako v původní otázce nebo polymorfismus (pokud to váš jazyk podporuje). Samozřejmě to není vždy možné, ale hledal bych řešení, které by jako první krok vyhýbalo switch ...

23
Dean Harding
switch (which) {
  case 0: comment = "String 1"; break;
  case 1: comment = "String 2"; break;
  case 2: comment = "String 3"; break;
  default: comment = "Oops"; break;
}

Výše uvedený způsob psaní tohoto typu přepínače je docela běžný. Důvod, proč jste cítil případ přepínače, pokud je objemnější, protože vaše tělo bylo pouze na jedné řádce a v případě přepínače jste také potřebovali prohlášení o přerušení. Takže skříň spínače měla dvojnásobnou velikost těla, než kdyby. S podstatnějším kódem přestane příkaz break k tělu příliš přispívat. Pro jednořádkové tělo je běžnou praxí psát kód na stejném řádku jako příkaz case.

Jak již uvedli ostatní, případ přepínače objasňuje záměr, chcete se rozhodnout na základě hodnoty jedné proměnné/výrazu. Mé komentáře jsou čistě z hlediska čitelnosti a nejsou založeny na výkonu.

14
aufather

V tomto případě příkaz switch jasněji odpovídá záměru kódu: vyberte akci, která se má provést na základě jediné hodnoty.

Čtení na druhé straně je však mnohem těžší číst - musíte se na ně všechny podívat, abyste si byli jisti, co se děje. Pro mě je to menší kód (i když počet znaků může být o něco vyšší), protože je méně duševně analyzovat.

8
FinnNk

Souhlasím s Jerrym, že řada řetězců je pro tento konkrétní případ lepší, ale obecně je lepší použít příkaz switch/case než řetězec jinde. Je snazší číst a kompilátor může někdy optimalizovat tento způsob lépe, ale je tu také další výhoda: je to mnohem jednodušší ladění.

Když stisknete tento přepínač, musíte udělat krok pouze jednou, abyste skončili na pravé větvi, místo toho, abyste opatrně překračovali několik příkazů najednou najednou, a možná trefíte klíč příliš rychle a překonali ho a něco chyběli a měli začít znovu.

8
Mason Wheeler

V takových případech dávám přednost přepínači, mnohem lépe odpovídá bodu kódu, pro každou jinou vstupní hodnotu spusťte jiný příkaz. if..else Funguje spíše jako „trik“, aby bylo dosaženo stejného efektu.

Příkazy switch jsou také čistší, je snadné mít překrytí překlepů ve všech těch ==

Také u velkých bloků v C je přepnutí rychlejší.

else..if Může být vhodnější, když máte něco jako rozsahy (mezi 1 a 100, to udělejte, mezi 100 a 200 to), nebo v C, když se pokusíte přepnout pomocí elementů, jako jsou řetězce (to je možné v jiných jazycích). Což je stejné.

Když programuji v C., mám tendenci používat mnoho přepínačů.

3
Khelben

Obecně se mi nelíbí ani jeden přístup. Dlouhý přepínač nebo pokud příkazy jen prosí, aby se refaktorovaly na objektově orientovanou abstrakci (váš příklad bych však klasifikoval jako krátký, ne dlouhý).

Osobně bych zabalil tento druh kódu do samostatné pomocné metody.

private string GetInsult()
{
    int which = (int)(Math.random() * 3);  //  Result is 0, 1, or 2.

    switch (which) {
        case 0: return "You look so much better than usual.";
        case 1: return "Your work is up to its usual standards.";
        case 2: return "You're quite competent for so little experience.";
        default: return "Oops -- something is wrong with this code.";
    }
}

public void Foo()
{
    string comment = GetInsult();
    Print(comment);
}

Umístění přepínače samostatnou metodou umožňuje umisťovat návratové příkazy přímo do příkazu přepínače (alespoň v c #), což eliminuje potřebu přerušovacích příkazů, čímž je kód mnohem snadněji čitelný.

A to je imho mnohem hezčí než přístup if/else if/else if.

2
Pete

Vyberte si něco, co je efektivní, pevné a pak dokument nejen to, co jste udělali, ale proč.

Kód může revidovat, a ne vždy jeho původní autor.

Jsou chvíle, kdy byste si mohli záměrně zvolit jednu implementaci před druhou protože dopředu uvažujete o kódu, který neexistuje.

2
Walt Stoneburner

Jednou z věcí, která dělá styl C/C # switch obzvláště nepříjemným, je naléhání na to, aby hodnota case byla literály. Jedna pěkná věc na VB/VB.NET je, že select/case umožňuje, aby byl každý případ jakýmkoli booleovským výrazem. To je výhodné. Pokud je často užitečná řada vzájemně se vylučujících booleovských výrazů, řada if/else ifs je flexibilnější, nemluvě o efektivnější psaní a čtení.

0
Joel Brown

V pythonu není příkaz pro přepnutí, protože pokud/Elif/else je Nice:

a = 5

if a==1:
    print "do this"
Elif a == 2:
    print "do that"
Elif a == 3:
    print "do the other"
Elif 3 < a < 9:
    print "do more"
Elif 9 <= a < 15:
    print "do nothing"
else:
    print "say sorry"

Jednoduché, že?

0