2010-05-30 8 views
18

Ho appena iniziato a imparare C# e sono rimasto bloccato a qualcosa di molto semplice.Usa intervalli decimali in uno switch impossibile in C#?

Per la mia prima "app" ho pensato di andare per qualcosa di semplice, così ho deciso per un calcolatore BMI.

Il BMI è calcolato in un tipo decimale che sto cercando di utilizzare in un'istruzione switch, ma decimale non può essere utilizzato in un interruttore?

Quale sarebbe la soluzione C# per questo:

  decimal bmi = calculate_bmi(h, w); 

      switch (bmi) { 
       case < 18.5: 
        bmi_description = "underweight."; 
        break; 
       case > 25: 
        bmi_description = "overweight"; 
       case > 30: 
        bmi_description = "very overweight"; 
       case > 40: 
        bmi_description = "extreme overweight"; 
        break; 
      } 
+0

Irony: http://stackoverflow.com/questions/2875533/che-funzionalità-del-tuono-del-vita-in-net-5-c-5/2876114#2876114 – Dykam

risposta

14

La dichiarazione switch supporta solo integral types (enumerazioni non sono elencati, ma possono essere utilizzati con switch dichiarazioni perché sono supportati da un tipo integrale) (stringhe sono supportati anche come sottolineato da Changeling - Vedere il commento per riferimento) e l'uguaglianza confronti con valori costanti. Pertanto è necessario utilizzare alcune istruzioni if.

if (bmi < 18.5M) 
{ 
    bmi_description = "underweight."; 
} 
else if (bmi <= 25) 
{ 
    // You missed the 'normal' case in your example. 
} 
else if (bmi <= 30) 
{ 
    bmi_description = "overweight"; 
} 
else if (bmi <= 40) 
{ 
    bmi_description = "very overweight"; 
} 
else 
{ 
    bmi_description = "extreme overweight"; 
} 

Tra l'altro la vostra istruzione switch è un po 'weired perché si sta passando da meno di a più di e-caduta attraverso l'utilizzo senza interruzioni. Penso che si dovrebbe usare solo un tipo di confronto per rendere il codice più facile da capire o riordinare i controlli e non usare fall-through.

if (bmi < 18.5M) 
{ 
    bmi_description = "underweight."; 
} 
else if (bmi > 40) 
{ 
    bmi_description = "extreme overweight"; 
} 
else if (bmi > 30) 
{ 
    bmi_description = "very overweight"; 
} 
else if (bmi > 25) 
{ 
    bmi_description = "overweight"; 
} 
else 
{ 
    // You missed the 'normal' case in your example. 
} 
+0

Questo è leggermente impreciso. L'operatore di commutazione può anche utilizzare le stringhe. Vedere qui: http://msdn.microsoft.com/en-us/library/06tc147t%28VS.71%29.aspx –

+1

Grazie per averlo indicato; aggiornato la risposta. –

+0

Grazie per l'aiuto! Il M dopo il decimale del 18,5 era quello che mancava dalle altre soluzioni, quindi questo l'ha risolto per me. Esiste un "nome" per ciò che fa M, in modo che io possa fare qualche ulteriore lettura su di esso? – phobia

9

Questo non è possibile con switch dichiarazioni in C#.
Il motivo è perché ogni istruzione case richiede un'espressione costante dopo di essa.

Inoltre, ogni valore è consentito una sola volta e il tipo dell'espressione deve corrispondere al tipo nel proprio switch. Nel tuo caso questo non è il caso perché volevi avere bool tipo case dichiarazioni ma un decimale nel tuo switch.

Considerare refactoring utilizzando una funzione di supporto, invece:

//... 
decimal bmi = calculate_bmi(h, w); 
string bmi_description = get_description_for_bmi(bmi); 
//... 

string get_description_for_bmi(decimal bmi) 
{ 
    string desc; 
    if(bmi < 18.5m) 
     desc = "underweight"; 
    else if(bmi <= 25) 
     desc = "average";//You forgot this one btw 
    else if(bmi <= 30) 
     desc = "overweight"; 
    else if(bmi <= 40) 
     desc = "very overweight";  
    else 
     desc = "extreme overweight"; 

    return desc; 
} 

Ulteriori approfondimenti:

Non solo sono valori di intervallo non ammessi, ma le espressioni non costanti non sono inoltre ammessi.

Ecco un esempio di qualcosa che non è possibile:

bool b = true; 
bool y = false; 
switch (b) 
{ 
    case true: 
     break; 
    case y: 
     break; 
} 

Tuttavia questo è possibile:

bool b = true; 
const bool y = false; 
switch (b) 
{ 
    case true: 
     break; 
    case y: 
     break; 
} 
+0

Puoi renderlo più semplice : non è necessario controllare 'bmi> 18.5', dato che ci si trova in' else'. Lo stesso vale per i seguenti test. 'if (bmi <= 18.5) ... else if (bmi <= 25) ... else if (bmi <= 30) ...' –

+0

@Thomas: Vero grazie, risolto. –

+0

A * esattamente * corrisponde al comportamento del codice dalla domanda che dovrebbe essere <18,5 anziché <= 18,5. –

0

Si potrebbe anche usare un qualche tipo di raccolta che archivia valori di cutoff e descrizioni. (Non sono un esperto di C# ... forse Dictionary<decimal,string>?) Scorri attraverso di esso per trovare l'ultimo che è inferiore al tuo bmi e restituisci l'etichetta corrispondente.

+0

sì, questa sembra una buona soluzione ... dovresti essere in grado di scorrere la chiave o il valore abbastanza facilmente utilizzando una raccolta generica come Dizionario. Se ti senti abbastanza sicuro usa un generico altrimenti prova a usare un enumeratore come un enum e attiva i valori costanti che una variabile enum attualmente contiene. – IbrarMumtaz

0

La parola chiave switch funziona perfettamente con i decimali. È < e> che ti stanno dando problemi.

+0

Switch * non * coopera con decimale (inoltre questo è nuovo in 4.0). –

1

vostro ulteriore sezione di lettura,

interruttori possono essere azionati solo con valori o casi in cui il valore di ingresso è un valore costante che l'interruttore può cercare come un indice ed eseguire il codice allegato definita all'interno di una custodia o case point o etichetta case, qualunque cosa possa essere usata in modo intercambiabile.

Modificare y su vero nel primo esempio e l'interruttore deve funzionare su "b".

Il secondo esempio funziona perché il secondo caso attiva un valore costante o "const". Quindi stai rispondendo ai criteri di base o a cosa serve un interruttore. Anche se molti qui vi diranno sicuramente di non codificare in questo modo. Attiva un semplice valore costante e assicurati che il tuo switch soddisfi in modo accurato ciascuno dei diversi valori che potrebbe essere la tua variabile fornita.

Provare a utilizzare un enum per rendere il codice in linea con le pratiche di codifica .Net standard questo commento si adatta anche a fare in modo che non si raccolgano cattive abitudini se si vuole fare una carriera di questo ???

RICORDARE: che è possibile utilizzare un enum e configurarlo per utilizzare valori decimali in quanto il valore decimale è un tipo di valore, in modo che questo soddisfi i criteri di ciò che richiede un enum. Poiché enum è definito nel framework .Net come un tipo di valore, è possibile impostare solo tipi di valori come i tipi basati su numeri per creare un tipo enum nelle tue classi di codice personalizzate. Allega semplicemente ogni valore con un nome o un tipo come hai usato sopra, come peso eccessivo, ecc. E assicurati che ogni voce nell'enumerazione abbia un ordinamento logico. I passaggi in termini di valori decimali hanno una chiara definizione di salire o scendere. Una volta impostato il tuo enum, crea una variabile del tipo di enum appena creato e quindi fornisci questa variabile al tuo switch.

Buon divertimento.