Modi per eliminare il cambio nel codice [chiuso]


175

Quali sono i modi per eliminare l'uso dello switch nel codice?


18
Perché dovresti voler eliminare gli interruttori, se usati in modo appropriato? Per favore, puoi approfondire la tua domanda.
RB.

Vedo che questa domanda può essere modificata dalla comunità perché tutti dicono la stessa cosa e potrebbe essere bello consolidare tutte le opinioni;)
Josh

2
Switch non è standard come le altre istruzioni. Ad esempio, in C ++, è probabile che si dimentichi la "pausa" e quindi si avranno risultati imprevisti. Inoltre, questa "pausa" è troppo simile a un GOTO. Non ho mai provato ad eliminare gli switch, ma di sicuro non sono le mie istruzioni preferite. ;)

2
Penso che si riferisca al concetto di switch e non all'istruzione switch C ++ o Java. Un interruttore può anche essere una catena di blocchi "if-else if".
Programmatore fuorilegge il

2
Potresti essere divertito: ci sono molti programmatori famosi della community agile che si unisce alla campagna anti-IF: antiifcampaign.com/supporters.html
Mike A

Risposte:


267

Le istruzioni switch non sono di per sé un antipattern, ma se stai codificando orientato agli oggetti dovresti considerare se l'uso di uno switch è meglio risolto con polimorfismo invece di usare un'istruzione switch.

Con il polimorfismo, questo:

foreach (var animal in zoo) {
    switch (typeof(animal)) {
        case "dog":
            echo animal.bark();
            break;

        case "cat":
            echo animal.meow();
            break;
    }
}

diventa questo:

foreach (var animal in zoo) {
    echo animal.speak();
}

2
Sono stato picchiato a causa di suggerimenti simili in stackoverflow.com/questions/374239/… Così tanti ppl non credono nel polimorfismo :) Ottimo esempio.
Nazgob,

30
-1: Non ho mai usato un'istruzione switch con typeof, e questa risposta non suggerisce modi o ragioni per aggirare le istruzioni switch in altre situazioni.
Kevin,

3
Sono d'accordo con @Kevin - l'esempio dato non mostra davvero come eliminare il passaggio dal polimorfismo. I semplici esempi: ottenere il nome di enum cambiando i suoi valori o eseguire un codice con i valori appropriati in un qualche tipo di algoritmo.
HotJard,

Mi chiedevo come eliminarlo prima di poter fare affidamento su implementazioni specifiche, ad esempio in una fabbrica. E ho trovato un grande esempio qui stackoverflow.com/a/3434505/711855
juanmf

1
esempio molto banale.
GuardianX,

239

Vedi l' odore delle dichiarazioni degli interruttori :

In genere, istruzioni di switch simili sono sparse in un programma. Se aggiungi o rimuovi una clausola in un interruttore, spesso devi trovare e riparare anche gli altri.

Sia Refactoring che Refactoring to Patterns hanno approcci per risolvere questo problema.

Se il tuo codice (pseudo) è simile a:

class RequestHandler {

    public void handleRequest(int action) {
        switch(action) {
            case LOGIN:
                doLogin();
                break;
            case LOGOUT:
                doLogout();
                break;
            case QUERY:
               doQuery();
               break;
        }
    }
}

Questo codice viola il principio aperto aperto ed è fragile per ogni nuovo tipo di codice di azione che si presenta. Per porre rimedio a ciò, è possibile introdurre un oggetto "Command":

interface Command {
    public void execute();
}

class LoginCommand implements Command {
    public void execute() {
        // do what doLogin() used to do
    }
}

class RequestHandler {
    private Map<Integer, Command> commandMap; // injected in, or obtained from a factory
    public void handleRequest(int action) {
        Command command = commandMap.get(action);
        command.execute();
    }
}

Se il tuo codice (pseudo) è simile a:

class House {
    private int state;

    public void enter() {
        switch (state) {
            case INSIDE:
                throw new Exception("Cannot enter. Already inside");
            case OUTSIDE:
                 state = INSIDE;
                 ...
                 break;
         }
    }
    public void exit() {
        switch (state) {
            case INSIDE:
                state = OUTSIDE;
                ...
                break;
            case OUTSIDE:
                throw new Exception("Cannot leave. Already outside");
        }
    }

Quindi è possibile introdurre un oggetto "Stato".

// Throw exceptions unless the behavior is overriden by subclasses
abstract class HouseState {
    public HouseState enter() {
        throw new Exception("Cannot enter");
    }
    public HouseState leave() {
        throw new Exception("Cannot leave");
    }
}

class Inside extends HouseState {
    public HouseState leave() {
        return new Outside();
    }
}

class Outside extends HouseState {
    public HouseState enter() {
        return new Inside();
    }
}

class House {
    private HouseState state;
    public void enter() {
        this.state = this.state.enter();
    }
    public void leave() {
        this.state = this.state.leave();
    }
}

Spero che questo ti aiuti.


7
Grazie per l'ottimo esempio su come refactificare il codice. Anche se potrei dire all'inizio, è un po 'difficile da leggere (perché si deve passare tra diversi file per capirlo completamente)
rshimoda,

8
Gli argomenti contro switch sono validi fintanto che ti rendi conto che la soluzione polimorfica sacrifica la semplicità del codice. Inoltre, se memorizzi sempre i casi switch in enum, alcuni compilatori ti avvertiranno che gli stati mancano dallo switch.
Harvey,

1
Questo è un ottimo esempio di operazioni complete / incomplete e, naturalmente, di ristrutturazione del codice in OOP. Grazie mille. Penso che sarà utile se i sostenitori di OOP / Design Patterns suggeriscano di trattare i concetti di OOP come operatori piuttosto che concetti . Voglio dire che "estensioni", "fabbrica", "attrezzi", ecc. Sono usati così spesso in file, classi, rami. Dovrebbero essere semplici come operatori come "+", "-", "+ =", "?:", "==", "->" ecc. Quando un programmatore li usa nella sua mente semplicemente come operatori, solo poi può riflettere su tutta la libreria di classi sullo stato del programma e (in) completare le operazioni.
namespaceform

13
Sto iniziando a pensare che SWITCH sia molto più comprensibile e logico, rispetto a questo. E di solito mi piace molto OOP, ma questa risoluzione mi sembra troppo astratta
JK,

1
Con l'oggetto Command, il codice da generare Map<Integer, Command>non avrebbe bisogno di un interruttore?
ataulm,

41

Un interruttore è un modello, sia implementato con un'istruzione switch, se altrimenti catena, tabella di ricerca, polimorfismo di oop, abbinamento di modelli o qualcos'altro.

Vuoi eliminare l'uso della " istruzione switch " o " switch pattern "? Il primo può essere eliminato, il secondo, solo se è possibile utilizzare un altro modello / algoritmo e il più delle volte ciò non è possibile o non è un approccio migliore per farlo.

Se vuoi eliminare l' istruzione switch dal codice, la prima domanda da porsi è dove ha senso eliminare l'istruzione switch e usare qualche altra tecnica. Purtroppo la risposta a questa domanda è specifica del dominio.

E ricorda che i compilatori possono fare varie ottimizzazioni per cambiare le istruzioni. Ad esempio, se si desidera eseguire l'elaborazione dei messaggi in modo efficiente, un'istruzione switch è praticamente la strada da percorrere. D'altra parte, l'esecuzione di regole aziendali basate su un'istruzione switch non è probabilmente il modo migliore per procedere e l'applicazione dovrebbe essere rearchitected.

Ecco alcune alternative per cambiare istruzione:


1
Qualcuno potrebbe fare un confronto tra l'elaborazione dei messaggi usando switch e altre alternative?
Mike A

37

Switch in sé non è poi così male, ma se hai molti "switch" o "if / else" su oggetti nei tuoi metodi, potrebbe essere un segno che il tuo design è un po '"procedurale" e che i tuoi oggetti sono solo valore secchi. Sposta la logica sui tuoi oggetti, invoca un metodo sui tuoi oggetti e lascia che decidano invece come rispondere.


Supponendo ovviamente che non stia scrivendo in C. :)
Bernard,

1
in C, può (ab?) usare i puntatori e le strutture di funzione per costruire qualcosa di simile ad un oggetto;)
Tetha,

Puoi scrivere FORT ^ H ^ H ^ H ^ H Java in qualsiasi lingua. ; p
Bernard,

Completamente d'accordo - switch è un ottimo modo per ridurre le righe di codice, ma non giocarci troppo.
HotJard,

21

Penso che il modo migliore sia usare una buona mappa. Usando un dizionario puoi mappare quasi tutti gli input ad altri valori / oggetti / funzioni.

il tuo codice sarebbe simile a (psuedo) come questo:

void InitMap(){
    Map[key1] = Object/Action;
    Map[key2] = Object/Action;
}

Object/Action DoStuff(Object key){
    return Map[key];
}

4
Dipende dalla lingua. Può essere molto meno leggibile di un interruttore
Vinko Vrsalovic,

Questa è una bella soluzione elegante nella giusta situazione. Di recente ho fatto questi codici chiave di mappatura e mi è sembrato di leggere bene a tale scopo.
Bernard,

Questo è vero, probabilmente non lo userei per niente di semplice, ma offre una certa flessibilità in termini di configurazione su un'istruzione switch. Un dizionario può essere preparato al volo mentre un interruttore sarà sempre codificato.
Josh,

Può essere più pulito in alcune circostanze. Anche più lento, poiché richiede chiamate di funzione.
Nick Johnson,

1
Dipende dalle tue chiavi. Un compilatore può compilare un'istruzione switch in una semplice ricerca o in una ricerca binaria statica estremamente veloce, in entrambi i casi senza richiedere alcuna chiamata di funzione.
Nick Johnson,

12

Tutti adorano i if elseblocchi ENORMI . Così facile da leggere! Sono curioso di sapere perché vorresti rimuovere le istruzioni switch, però. Se hai bisogno di un'istruzione switch, probabilmente hai bisogno di un'istruzione switch. Scherzi a parte, direi che dipende da cosa sta facendo il codice. Se tutto ciò che lo switch sta facendo è chiamare funzioni (diciamo) potresti passare i puntatori a funzione. Se è una soluzione migliore è discutibile.

La lingua è un fattore importante anche qui, penso.


13
Immagino che fosse il sarcasmo :)
Craig Day

6

Penso che quello che stai cercando sia il modello strategico.

Questo può essere implementato in diversi modi, che sono stati menzionati in altre risposte a questa domanda, come ad esempio:

  • Una mappa di valori -> funzioni
  • Polimorfismo. (il sottotipo di un oggetto deciderà come gestire un processo specifico).
  • Funzioni di prima classe.

5

switch le dichiarazioni sarebbero buone da sostituire se ti ritrovi ad aggiungere nuovi stati o nuovi comportamenti alle dichiarazioni:

int state;

String getString () {
   switch (stato) {
     caso 0: // comportamento per lo stato 0
           ritorna "zero";
     caso 1: // comportamento per lo stato 1
           restituisce "uno";
   }
   lanciare nuovo IllegalStateException ();
}

doppio getDouble () {

   switch (this.state) {
     caso 0: // comportamento per lo stato 0
           ritorna 0d;
     caso 1: // comportamento per lo stato 1
           ritorno 1d;
   }
   lanciare nuovo IllegalStateException ();
}

L'aggiunta di nuovi comportamenti richiede la copia di switch, e l'aggiunta di nuovi stati significa aggiungere un altro casea ogni switch istruzione.

In Java, è possibile cambiare solo un numero molto limitato di tipi primitivi di cui si conoscono i valori in fase di esecuzione. Questo presenta un problema in sé e per sé: gli stati vengono rappresentati come numeri o personaggi magici.

if - elseÈ possibile utilizzare la corrispondenza dei modelli e più blocchi, sebbene abbiano gli stessi problemi quando si aggiungono nuovi comportamenti e nuovi stati.

La soluzione che altri hanno suggerito come "polimorfismo" è un'istanza del modello statale :

Sostituisci ciascuno degli stati con la propria classe. Ogni comportamento ha il suo metodo sulla classe:

Stato IState;

String getString () {
   return state.getString ();
}

doppio getDouble () {
   return state.getDouble ();
}

Ogni volta che aggiungi un nuovo stato, devi aggiungere una nuova implementazione IStatedell'interfaccia. In un switchmondo, aggiungeresti uno casea ciascuno switch.

Ogni volta che aggiungi un nuovo comportamento, devi aggiungere un nuovo metodo IStateall'interfaccia e ciascuna delle implementazioni. Questo è lo stesso onere di prima, sebbene ora il compilatore controllerà che tu abbia implementazioni del nuovo comportamento su ogni stato preesistente.

Altri hanno già detto che questo potrebbe essere troppo pesante, quindi ovviamente c'è un punto che raggiungi dove ti sposti da uno all'altro. Personalmente, la seconda volta che scrivo un interruttore è il punto in cui refactoring.


4

se altro

Respingo la premessa secondo cui l'interruttore è intrinsecamente negativo.


3

Bene, per esempio, non sapevo che usare switch fosse un anti pattern.

In secondo luogo, è sempre possibile sostituire switch con if / else if.


esattamente - switch è solo metadone sintattico per un gruppo di if / elsifs.
Mike A

3

Perché vuoi Nelle mani di un buon compilatore, un'istruzione switch può essere molto più efficiente rispetto ai blocchi if / else (oltre ad essere più facile da leggere) e è probabile che solo gli switch più grandi vengano accelerati se vengono sostituiti da qualsiasi tipo della struttura dei dati di ricerca indiretta.


2
A quel punto indovini il compilatore e apporti modifiche al tuo design sulla base degli interni del compilatore. Il design dovrebbe seguire la natura del problema, non la natura del compilatore.
Mike A

3

'switch' è solo un costrutto di linguaggio e tutti i costrutti di linguaggio possono essere pensati come strumenti per svolgere un lavoro. Come con gli strumenti reali, alcuni strumenti si adattano meglio a un'attività piuttosto che a un'altra (non si userebbe una mazza per montare un gancio per foto). La parte importante è come viene definito "portare a termine il lavoro". Deve essere mantenibile, deve essere veloce, deve essere ridimensionato, deve essere estensibile e così via.

Ad ogni punto del processo di programmazione di solito ci sono una serie di costrutti e modelli che possono essere usati: un interruttore, una sequenza if-else-if, funzioni virtuali, tabelle di salto, mappe con puntatori a funzione e così via. Con l'esperienza un programmatore conoscerà istintivamente lo strumento giusto da utilizzare per una determinata situazione.

Si deve presumere che chiunque mantenga o riveda il codice sia esperto almeno quanto l'autore originale in modo che qualsiasi costrutto possa essere usato in sicurezza.


OK, ma perché abbiamo bisogno di 5 modi diversi e ridondanti di fare la stessa cosa: l'esecuzione condizionale?
Mike A

@ mike.amy: perché ogni metodo ha diversi vantaggi e costi ed è tutto per ottenere il massimo beneficio con il minor costo.
Skizz,

1

Se l'interruttore è lì per distinguere tra vari tipi di oggetti, probabilmente ti mancheranno alcune classi per descrivere con precisione quegli oggetti o alcuni metodi virtuali ...


1

Per C ++

Se ti riferisci ad esempio a una AbstractFactory, penso che un metodo registerCreatorFunc (..) di solito sia meglio che richiedere di aggiungere un caso per ogni "nuova" istruzione necessaria. Quindi, lasciando che tutte le classi creino e registrino una creatorFunction (..) che può essere facilmente implementata con una macro (se oso citare). Credo che questo sia un approccio comune a molti framework. L'ho visto per la prima volta in ET ++ e penso che molti framework che richiedono una macro DECL e IMPL lo utilizzino.


1

In un linguaggio procedurale, come C, quindi passare sarà migliore di una qualsiasi delle alternative.

In un linguaggio orientato agli oggetti, ci sono quasi sempre altre alternative disponibili che utilizzano meglio la struttura dell'oggetto, in particolare il polimorfismo.

Il problema con le istruzioni switch si presenta quando si verificano diversi blocchi switch molto simili in più punti dell'applicazione e deve essere aggiunto il supporto per un nuovo valore. È abbastanza comune per uno sviluppatore dimenticare di aggiungere il supporto per il nuovo valore a uno dei blocchi di switch sparsi nell'applicazione.

Con il polimorfismo, una nuova classe sostituisce il nuovo valore e il nuovo comportamento viene aggiunto come parte dell'aggiunta della nuova classe. Il comportamento in questi punti di commutazione viene quindi ereditato dalla superclasse, sovrascritto per fornire un nuovo comportamento o implementato per evitare un errore del compilatore quando il super metodo è astratto.

Laddove non è in atto un polimorfismo evidente, può valere la pena implementare il modello strategico .

Ma se la tua alternativa è un grande blocco IF ... THEN ... ELSE, allora dimenticalo.


1

Utilizzare una lingua che non viene fornita con un'istruzione switch integrata. Mi viene in mente Perl 5.

Scherzi a parte, perché dovresti evitarlo? E se hai buone ragioni per evitarlo, perché non semplicemente evitarlo, allora?


1

I puntatori a funzione sono un modo per sostituire un'enorme istruzione switch pesante, sono particolarmente buoni nelle lingue in cui è possibile acquisire funzioni con i loro nomi e fare cose con loro.

Ovviamente, non dovresti forzare le istruzioni switch a uscire dal tuo codice, e c'è sempre la possibilità che tu stia sbagliando tutto, il che si traduce in stupide parti ridondanti di codice. (Questo è inevitabile a volte, ma una buona lingua dovrebbe consentire di rimuovere la ridondanza pur rimanendo pulito.)

Questo è un grande esempio di divisione e conquista:

Supponi di avere un interprete di qualche tipo.

switch(*IP) {
    case OPCODE_ADD:
        ...
        break;
    case OPCODE_NOT_ZERO:
        ...
        break;
    case OPCODE_JUMP:
        ...
        break;
    default:
        fixme(*IP);
}

Invece, puoi usare questo:

opcode_table[*IP](*IP, vm);

... // in somewhere else:
void opcode_add(byte_opcode op, Vm* vm) { ... };
void opcode_not_zero(byte_opcode op, Vm* vm) { ... };
void opcode_jump(byte_opcode op, Vm* vm) { ... };
void opcode_default(byte_opcode op, Vm* vm) { /* fixme */ };

OpcodeFuncPtr opcode_table[256] = {
    ...
    opcode_add,
    opcode_not_zero,
    opcode_jump,
    opcode_default,
    opcode_default,
    ... // etc.
};

Si noti che non so come rimuovere la ridondanza di opcode_table in C. Forse dovrei fare una domanda al riguardo. :)


0

La risposta più ovvia, indipendente dalla lingua, è quella di utilizzare una serie di "if".

Se la lingua che stai utilizzando ha i puntatori a funzione (C) o ha funzioni che sono valori di 1a classe (Lua), puoi ottenere risultati simili a uno "switch" usando un array (o un elenco) di funzioni (puntatori a).

Dovresti essere più specifico sulla lingua se vuoi risposte migliori.


0

Le istruzioni switch possono spesso essere sostituite da un buon design OO.

Ad esempio, hai una classe Account e stai utilizzando un'istruzione switch per eseguire un calcolo diverso in base al tipo di account.

Vorrei suggerire che questo dovrebbe essere sostituito da un numero di classi di account, che rappresentano i diversi tipi di account e tutti implementano un'interfaccia Account.

Lo switch diventa quindi non necessario, poiché puoi trattare tutti i tipi di account allo stesso modo e grazie al polimorfismo, verrà eseguito il calcolo appropriato per il tipo di account.


0

Dipende dal motivo per cui si desidera sostituirlo!

Molti interpreti usano "goto calcolate" invece di istruzioni switch per l'esecuzione di opcode.

Quello che mi manca dello switch C / C ++ è Pascal 'in' e intervalli. Vorrei anche poter attivare le stringhe. Ma questi, sebbene banali da mangiare per un compilatore, sono un duro lavoro quando si usano strutture, iteratori e cose. Quindi, al contrario, ci sono molte cose che vorrei poter sostituire con un interruttore, se solo l'interruttore C () fosse più flessibile!


0

Switch non è un buon modo di procedere poiché interrompe l'Open Close Principal. Questo è come lo faccio.

public class Animal
{
       public abstract void Speak();
}


public class Dog : Animal
{
   public virtual void Speak()
   {
       Console.WriteLine("Hao Hao");
   }
}

public class Cat : Animal
{
   public virtual void Speak()
   {
       Console.WriteLine("Meauuuu");
   }
}

Ed ecco come usarlo (prendendo il tuo codice):

foreach (var animal in zoo) 
{
    echo animal.speak();
}

Fondamentalmente quello che stiamo facendo è delegare la responsabilità alla classe del bambino invece di far decidere al genitore cosa fare dei bambini.

Potresti anche voler leggere su "Principio di sostituzione di Liskov".


0

In JavaScript utilizzando l'array Associative:
questo:

function getItemPricing(customer, item) {
    switch (customer.type) {
        // VIPs are awesome. Give them 50% off.
        case 'VIP':
            return item.price * item.quantity * 0.50;

            // Preferred customers are no VIPs, but they still get 25% off.
        case 'Preferred':
            return item.price * item.quantity * 0.75;

            // No discount for other customers.
        case 'Regular':
        case
        default:
            return item.price * item.quantity;
    }
}

diventa questo:

function getItemPricing(customer, item) {
var pricing = {
    'VIP': function(item) {
        return item.price * item.quantity * 0.50;
    },
    'Preferred': function(item) {
        if (item.price <= 100.0)
            return item.price * item.quantity * 0.75;

        // Else
        return item.price * item.quantity;
    },
    'Regular': function(item) {
        return item.price * item.quantity;
    }
};

    if (pricing[customer.type])
        return pricing[customer.type](item);
    else
        return pricing.Regular(item);
}

Cortesia


-12

Un altro voto per if / else. Non sono un grande fan delle affermazioni sui casi o sui cambi perché ci sono persone che non li usano. Il codice è meno leggibile se si utilizza case o switch. Forse non meno leggibile per te, ma per quelli che non hanno mai avuto bisogno di usare il comando.

Lo stesso vale per le fabbriche di oggetti.

I blocchi if / else sono un costrutto semplice che tutti ottengono. Ci sono alcune cose che puoi fare per assicurarti di non causare problemi.

Primo: non cercare di indentare se le dichiarazioni più di un paio di volte. Se ti ritrovi a rientrare, allora stai sbagliando.

 if a = 1 then 
     do something else 
     if a = 2 then 
         do something else
     else 
         if a = 3 then 
             do the last thing
         endif
     endif 
  endif

È davvero male - fallo invece.

if a = 1 then 
   do something
endif 
if a = 2 then 
   do something else
endif 
if a = 3 then 
   do something more
endif 

L'ottimizzazione sia dannata. Non fa molta differenza per la velocità del tuo codice.

In secondo luogo, non sono contrario a uscire da un blocco If fintanto che ci sono abbastanza istruzioni break sparse attraverso il blocco di codice particolare per renderlo ovvio

procedure processA(a:int)
    if a = 1 then 
       do something
       procedure_return
    endif 
    if a = 2 then 
       do something else
       procedure_return
    endif 
    if a = 3 then 
       do something more
       procedure_return
    endif 
end_procedure

EDIT : su Switch e perché penso sia difficile grok:

Ecco un esempio di un'istruzione switch ...

private void doLog(LogLevel logLevel, String msg) {
   String prefix;
   switch (logLevel) {
     case INFO:
       prefix = "INFO";
       break;
     case WARN:
       prefix = "WARN";
       break;
     case ERROR:
       prefix = "ERROR";
       break;
     default:
       throw new RuntimeException("Oops, forgot to add stuff on new enum constant");
   }
   System.out.println(String.format("%s: %s", prefix, msg));
 }

Per me il problema qui è che le normali strutture di controllo che si applicano in linguaggi simili a C sono state completamente rotte. Esiste una regola generale che, se si desidera inserire più di una riga di codice all'interno di una struttura di controllo, utilizzare parentesi graffe o un'istruzione iniziale / finale.

per esempio

for i from 1 to 1000 {statement1; statement2}
if something=false then {statement1; statement2}
while isOKtoLoop {statement1; statement2}

Per me (e puoi correggermi se sbaglio), l'istruzione Case getta questa regola fuori dalla finestra. Un blocco di codice eseguito in modo condizionale non viene inserito in una struttura di inizio / fine. Per questo motivo, credo che Case sia concettualmente abbastanza diverso da non essere utilizzato.

Spero che risponda alle tue domande.


Caspita - ovviamente una risposta controversa. Sarei interessato a sapere cosa ho fatto di così sbagliato.
seanyboy,

Ehm, passare a essere troppo complesso? Non lo so ... mi sembra che non ci sarebbero molte funzionalità linguistiche che potresti usare. :) Inoltre, nel tuo esempio centrale, non sarebbe più intelligente fare se (a == 1 || a == 2 || a == 3) fare qualcosa?
Lars Westergren,

Inoltre, nel tuo ultimo esempio, "break" non farà nulla nella maggior parte delle lingue, che esce dal blocco più vicino (di solito un loop), che nel tuo caso si verifica comunque nella riga successiva (endif). Se usi una lingua in cui l'interruzione è "ritorno", anche molti ritorni sono disapprovati (tranne che per le "dichiarazioni di guardia")
Lars Westergren,

4
"L'ottimizzazione è dannata. Non fa molta differenza per la velocità del tuo codice." Il mio codice funziona su una piattaforma mobile. Le ottimizzazioni contano. Inoltre, gli switch possono rendere il codice MOLTO pulito (rispetto a if..elseif..elseif..elseif ...) se usato correttamente. Non li hai mai visti? Imparali.
Swati,

Switch non è affatto complicato, ma ho sempre cercato di ridurre al minimo il numero di costrutti utilizzati nel codice per ridurre l'attrito nella comprensione.
seanyboy,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.