2012-03-29 12 views
6

È sciocco da parte mia lasciare dichiarazioni di interruzione irraggiungibili in un caso che genera comunque un'eccezione? La parte difensiva di me vuole lasciarla lì nel caso in cui la logica cambi. Un'altra parte di me non vuole che altri sviluppatori vedano avvisi del compilatore sul mio codice ("Rilevato codice non raggiungibile").Devo lasciare un'interruzione irraggiungibile in un caso in cui lancio un'eccezione?

switch (someInt) 
{ 
    case 1: 
     // Do something 
     break; 
    case 2: 
     // Do something else 
     break; 
    case 3: 
     // Oh, we don't use threes here! 
     throw new Exception("Business rules say don't use 3 anymore"); 
     break; // Unreachable...until the fickle business rules change... 
    default: 
     throw new Exception("Some default exception"); 
     break; // Unreachable...until...well, you get the idea. 
} 

Cosa fare?

UPDATE

vedo alcune risposte dicendo che la rimozione del lancio ad una data successiva causerebbe un errore di compilazione. Tuttavia, semplicemente rimuovendo (o commentando) il lancio senza interruzioni, i casi potrebbero essere impilati. Non sto dicendo che è uno scenario probabile, ma ... beh, la programmazione difensiva riguarda la lotta solo a possibili scenari?

+1

Il 'break' non è più necessario, li rimuovo perché costruisco con avvisi come errori. – asawyer

+1

Interessante domanda: la mia prima reazione sarebbe quella di includere l'affermazione della pausa, ma penso che sarebbe semplicemente un'abitudine. – KazR

+1

disattiva avviso pragma se ritieni che la tua preoccupazione sia valida ma non vuoi disturbare gli altri, ma essere eccessivamente difensivo può ingombrare rapidamente il tuo codice base – Michael

risposta

6

I' d rimuoverli. Diversi motivi:

  • Tu non li servono al momento
  • Vedendo un sacco di avvertimenti mi fa sempre nervoso come si possono perdere le avvertenze reali nel rumore proveniente da questo tipo di avvertimento (ammesso che abbiate avvertono come errore off).
+0

Come ti mancheresti "errori reali?" O il tuo codice non verrà compilato o hai già deciso che un avviso non è un "errore reale" (ad esempio, non si crea con il flag "trattare gli avvertimenti come errori"). – Michael

+1

Se hai generato 150 avvisi generati sopra il livello di rumore e introduci un elemento che genera un avviso che è utile, sarà facile non vederlo. – gbanfill

0

La parte difensiva di me vuole lasciarlo lì nel caso in cui la logica cambi.

Quale logica è esattamente soggetta a modifiche qui? Ciò che accade quando viene lanciata un'eccezione è documentato abbastanza bene. E penso che tu possa essere ragionevolmente sicuro che nessuna revisione successiva alla C# avrà effetto su un cambiamento improvviso di "tutti i programmi scritti finora non funzionano più".

Anche se non ci sono avvisi del compilatore, il codice ridondante non è una buona cosa a meno che non ci sia la possibilità che il codice possa entrare in gioco impedendo bug durante la manutenzione di routine, che in questo caso non possiamo ragionevolmente dire che tale possibilità esiste.

+0

Penso che intenda se l'eccezione viene rimossa, ma anche così non è un problema come devi avere l'uno o l'altro. –

+0

Forse ho usato la terminologia sbagliata lì, ma no, non intendo se le specifiche C# cambiano, solo regole aziendali volubili. –

0

La parte difensiva di me vuole lasciarla lì nel caso in cui la logica cambi.

Beh, se si rimuove il throw e dimentica di aggiungere un break il compilatore vi farò sapere.

Non vedo alcuna ragione per la pausa di essere lì. È ridondante e si innescherà comunque un avvertimento, quindi lo rimuoverei. Non c'è una buona ragione per lasciare il codice inutile a ingombrare la tua logica.

+2

Semplicemente rimuovendo il lancio senza interruzioni, i casi potrebbero essere impilati, il che potrebbe essere un comportamento indesiderato. –

+0

@TimLehner: È vero perché il corpo sarebbe vuoto. Detto questo ... se hai lasciato il corpo vuoto, suppongo che tu l'abbia fatto per una ragione. Spero che ti fidi dei tuoi colleghi per sapere le basi su come funziona un interruttore. –

+0

Non speriamo tutti per le stesse cose, davvero? :) –

1

Lo rimuoverei.

E si libera delle avvertenze, e anche se la logica dovesse cambiare e la deroga da rimuovere, che ci si riceve un errore del compilatore dice che una rottura deve essere aggiunto indietro nel.

+0

Non solo un avvertimento, sarebbe un errore. –

+0

@ Eds., Hai ragione, mio ​​errore. – Brandon

+0

In realtà c'è un caso in cui entrambi abbiamo torto. Se l'eccezione viene rimossa e non viene aggiunto nulla, il corpo sarà vuoto e consentirà la ricaduta senza preavviso o errore. –

2

Ignorando alcuni avvisi del compilatore, si rinforza il cattivo comportamento di ignorare qualsiasi avviso del compilatore. A mio parere, questo è un rischio maggiore rispetto a qualsiasi vantaggio ottenuto lasciando le dichiarazioni break in.

EDIT: ho rimosso il mio punto originale sulla compilatore ti costringe a mettere le dichiarazioni break indietro nel se i throw dichiarazioni dovevano essere rimossi. Come ha sottolineato Payo, in alcuni casi, il compilatore non lo farebbe. Semplicemente combinerebbe il caso con quello sottostante.

+0

Il compilatore non ti obbliga ad aggiungere l'interruzione se il caso non ha altro codice (dopo aver commentato il lancio). – payo

+0

Hai ragione. In tal caso, l'onere è sul programmatore di scrivere un buon codice. – FishBasketGordo

2

Personalmente, non lascerei mai il codice irraggiungibile nel codice di produzione. Va bene per i test, ma non lasciarlo come tale.

Non lo faresti mai?

public void MyMethodThatThrows() 
{ 
    throw new Exception(); 
    return; // unneeded 
} 

quindi perché mantenere lo break?

+0

Capisco la prima parte di questo bene ed è un buon punto. L'esempio, tuttavia, è in qualche modo un uomo di paglia perché, mentre non inserirò un ritorno all'interno di un vuoto, certamente inserirò delle interruzioni all'interno di un interruttore. Ovviamente questa domanda riguarda le interruzioni piuttosto che i ritorni in un interruttore perché, beh, sono un tipo di uscita di un ragazzo. –

+0

@TimLehner, ha, buon punto. il mio esempio era fondamentalmente solo per esagerare il problema. –

7

Non lo "nascondere" nello switch. Vorrei lanciare il ArgumentExceptions il prima possibile. Ciò evita effetti collaterali ed è anche più trasparente.

Qualcuno potrebbe aggiungere il codice prima che l'interruttore ad un certo punto che utilizza someInt anche se è 3.

Ad esempio:

public void SomeMethod(int someInt) 
{ 
    if (someInt == 3) 
     throw new ArgumentException("someInt must not be 3", "someInt"); 

    switch (someInt) 
    { 
     // ... 
    } 
} 
+1

Punto eccellente e un buon odore di codice. –

0

Vorrei che le mie fonti di progetto erano così fresco e guai-less, che Dovrei pensare a casi minori di programmazione difensiva :)

Voglio dire ci sono così tante insidie ​​nello sviluppo del software - COM e Interop, Sicurezza/Permessi e Autenticazione, Certificati, che ... gosh , non posso dirti come molto codice dovrei scrivere per difendermi dalle riprese in piedi.

Basta rimuovere questa interruzione, perché è ridondante, è fonte di confusione per i borsisti che sanno che 'caso' dovrebbe terminare con break o return e dovrebbe diventare ovvio per gli utenti che non lo sanno.

+0

È vero, questo è il più grande problema di nessuno nella vita. Ora, il caso che termina in cambio è definitivamente in discussione ... –

0

MSDN C# Reference afferma: "Un'istruzione di salto come un'interruzione è necessaria dopo ogni blocco di casi, incluso l'ultimo blocco, sia che si tratti di un'istruzione case o di un'istruzione predefinita."

Quindi, il "lancio" non costituisce una "istruzione di salto"? Penso che lo faccia. Pertanto, "break" non è richiesto e il problema "irraggiungibile" scompare. :)

+0

Il PO ha riconosciuto che i 'break's non sono necessari, ma sta considerando di lasciarli in modo difensivo. Considera cosa succede se decidi di fare qualcosa di diverso da un'eccezione. – jerry