Sintassi dell'istruzione if / switch combinata con la gestione delle eccezioni per una lingua C # -inspirata

7

A volte è necessario provare / catturare le eccezioni all'interno della condizione "se", ma non il corpo che segue. In C #, questo è davvero piuttosto ingombrante, richiedendo a gente del posto e codice che non è del tutto ovvio, a colpo d'occhio, quanto al suo funzionamento.

A volte è anche necessario scrivere istruzioni "switch", che, a differenza di "if", hanno più di due possibili risultati, anche se in C # richiede l'uso di un discretamente impopolare sintassi.

Ecco un'idea per combinarli.

Unione di switch con try/catch

Per prima cosa, cambiamo la sintassi fondamentale di "switch" per essere vicini a sostituzione abbastanza popolare , ma senza i ricci extra:

switch (condition)
    case 1 { }
    case 2 { }
    default { }

Successivamente, rendiamo possibile rilevare le eccezioni nella condizione. Sotto il cofano, questo inserisce un blocco try / catch appropriato solo quando è presente almeno un catch :

switch (condition)
    catch FileNotFoundException e { } // use "e"
    catch ArgumentException { }
    catch { }
    case 1 { }
    case 2 { }
    default { }

Ora rendiamo più facile incatenare diverse affermazioni simili a quelle di if / else, spostando "predefinito" di un livello in alto e rinominandolo in "else":

switch (condition1)
    catch FileNotFoundException { }
    case 1 { }
    case 2 { }
else switch (condition2)
    case "abc" { }
    case "def" { }
else
    { }

E quindi abbiamo un switch unito a try/catch !

Combinazione con "if"

Sia switch che if ora hanno clausole else , quindi perché non ti permettono di mescolarli a tuo piacimento:

if (bool-condition1)
    { }
else if (bool-condition2)
    { }
else switch (string-expr)
    catch FileNotFoundException { }
    case "thing" { }
else
    { }

(grazie ach_l !)

Ulteriori miglioramenti

Attivare un elenco o un intervallo di valori è stato proposto e può essere facilmente incorporato:

switch (int-expression)
    case 1 { }
    case 2, 5 { }
    case 10..50 { }
else switch (string-expression)
    case "abc" { }
    case "def" { }
else if (boolean-condition3)
    { }
else
    { }

In questo caso potrebbe essere davvero comodo poter fare riferimento al valore nella clausola di condizione. Questo può essere facilmente incorporato consentendo a uno di dichiarare una singola variabile in questa clausola nello stesso modo in cui C #%% co_de consente:

switch (var z = int-expression)
    case 2, 5 { return z == 2 ? "two" : "five"; }
    case 10..50 { return (z * 10).ToString(); }

vantaggi

Tra gli altri vantaggi, uno può ora esprimere uno scenario di gestione degli errori comune in modo conciso, e tuttavia non WTFy :

switch (bool-condition)
    catch FileNotFoundException e { }
    case true { }
    case false { }

Questo risolverebbe qualsiasi difficoltà di codifica nella vita reale che hai incontrato? Ci sono delle modifiche che potresti applicare a questo?

    
posta Roman Starkov 16.04.2011 - 15:53
fonte

1 risposta

4

Personalmente lascerei if come valutazione di un argomento booleano con un vero percorso e facoltativo falso altro percorso, mentre switch potrebbe valutare altri oggetti per l'uguaglianza, l'appartenenza a un set, ecc. Potrebbe non essere una buona ragione, ma questo è il comportamento di if in molte altre lingue. Per cambiare questa definizione penso che rischieremmo di confondere nuovi programmatori.

Ma potrei vedere sicuramente utile questa sintassi dei blocchi catch e la possibilità di concatenare insieme ifs e switch potrebbe anche avere un caso d'uso.

Personalmente tendo ad apprezzare uno stile in cui il nome dell'argomento è definito dal blocco, Inoltre, se il valore di una condizione viene valutato, potremmo facoltativamente fornirlo anche ai blocchi del caso!

Forse questo esempio potrebbe far luce sulla portata di ciò che sto pensando di costruire su questo:

if(<boolean>condition1)
    catch Exception { e -> /* exception referenced by e */ } 
    { /*true*/ } 
else switch(<any>condition2) 
   catch FileNotFoundException { /* I don't care about this exception*/ }
   case 1 {  /* I don't need condition2's value */  }
   case 2, 5, 10 .. 20 { v -> /* v is condition 2 value */ } 
   case <50 { x -> /* x is condition 2's value, this would only be evaluated if other branches are not */}
else 
   { /* !condition1 and no case evaluated in condition 2 */ }
    
risposta data 16.04.2011 - 16:40
fonte

Leggi altre domande sui tag