2010-05-30 8 views
18

Właśnie zaczynam naukę C# i utknąłem w czymś bardzo podstawowym.Czy używanie dziesiętnych zakresów w przełączniku jest niemożliwe w języku C#?

Dla mojej pierwszej "aplikacji" myślałem, że pójdę na coś prostego, więc zdecydowałem się na kalkulator BMI.

BMI jest obliczany na liczbę dziesiętną, którą teraz próbuję użyć w instrukcji przełączania, ale dziesiętnie po przecinku nie można użyć w przełączniku?

Jaki byłby C# rozwiązanie tego problemu:

  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/what-features-do-you-want-to-see-in-net-5-c-5/2876114#2876114 – Dykam

Odpowiedz

14

Oświadczenie switch obsługuje tylko integral types (wyliczenia nie są wymienione, ale może być używany z switch sprawozdania, ponieważ są one wspierane przez integralny typu) (łańcuchy są również obsługiwane jak podkreślił Oszukana - patrz komentarz dla odniesienia) oraz równość porównania ze stałymi wartościami. Dlatego musisz użyć niektórych instrukcji 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"; 
} 

Przy okazji swoje oświadczenie przełącznik jest nieco weired dlatego, że przejście z mniej niż większy niż i-upadku poprzez zastosowanie bez przerw. Myślę, że należy użyć tylko jednego rodzaju porównań, aby kod był łatwiejszy do zrozumienia lub zmiany kolejności kontroli i nie używał ataku typu 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

To jest trochę niedokładne. Operator przełącznika może również używać łańcuchów. Zobacz tutaj: http://msdn.microsoft.com/en-us/library/06tc147t%28VS.71%29.aspx –

+1

Dzięki za wskazanie tego; zaktualizował odpowiedź. –

+0

Dzięki za pomoc! M po przecinku 18,5 był tym, czego brakowało w innych rozwiązaniach, więc ten rozwiązał dla mnie. Czy istnieje jakieś "imię" tego, co robi M, abym mógł przeczytać dalej? – phobia

9

To nie jest możliwe z switch wypowiedzi w języku C#.
Powód jest taki, że każde wyrażenie przypadku wymaga stałego wyrażenia po nim.

Każda wartość jest dozwolona tylko jeden raz, a typ wyrażenia musi być zgodny z typem w twoim switch. W twoim przypadku tak nie jest, ponieważ chcesz mieć instrukcje typu bool typu case, ale dziesiętny w swoim switch.

Rozważmy refactoring przy użyciu funkcji pomocnika zamiast:

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

Dalsze czytanie:

Nie tylko są wartościami zakres nie jest dozwolony, ale nie wyrażenia stałe nie są dozwolone.

Oto przykład czegoś, co nie jest możliwe:

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

jednak jest to możliwe:

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

Możesz uprościć : nie musisz sprawdzać 'bmi> 18.5', ponieważ jesteś w' else'. To samo dotyczy następujących testów. 'if (bmi <= 18,5) ... else if (bmi <= 25) ... else if (bmi <= 30) ...' –

+0

@Thomas: Prawdziwe dzięki, naprawione. –

+0

Aby * dokładnie * dopasować zachowanie kodu z pytania, powinno być <18,5 zamiast <= 18,5. –

0

można też użyć jakiegoś zbioru, który przechowuje wartości i opisy odcięcia. (Nie jestem ekspertem C# ... może Dictionary<decimal,string>?) Iteruj przez niego, aby znaleźć ostatni, który jest mniejszy niż twój bmi, i zwróć odpowiednią etykietę.

+0

tak to brzmi jak dobre rozwiązanie ... powinieneś być w stanie iterować po kluczu lub wartości całkiem łatwo przy użyciu ogólnej kolekcji, takiej jak Słownik. Jeśli czujesz się wystarczająco pewnie, użyj generycznego, spróbuj użyć modułu wyliczającego jak wyliczenia i włącz stałe wartości, które obecnie zawiera zmienna wyliczeniowa. – IbrarMumtaz

0

Słowo kluczowe przełączania działa dobrze z miejscami dziesiętnymi. To jest < i> które dają ci kłopoty.

+0

Przełącznik ma * nie * współpracuje z dziesiętnym (oprócz tego jest nowy w wersji 4.0). –

1

Twój dalszy odcinek czytanie,

przełączniki mogą być eksploatowane tylko na wartościach lub przypadków, przy czym wartość wejściowa jest wartością stałą, że przełącznik może patrzeć jak indeks i wykonanie załączonego kodu zdefiniowana wewnątrz obudowy lub etykieta przypadku lub etykieta przypadku, niezależnie od tego, czy wszystkie mogą być używane zamiennie.

Zmień y na true w pierwszym przykładzie, a przełącznik powinien działać na "b".

Drugi przykład działa, ponieważ drugi przypadek włącza stałą lub wartość "const". Dlatego spełniasz podstawowe kryteria lub to, czego potrzebuje przełącznik. Chociaż wielu z nich na pewno powie ci, żebyś tak nie kodował. Włącz prostą stałą wartość i upewnij się, że twój przełącznik dokładnie odpowiada każdej z różnych wartości, jakie może dostarczyć twoja dostarczona zmienna.

Spróbuj użyć enum, aby twój kod był zgodny ze standardowymi praktykami kodowania .Net, ten komentarz również zgadza się z upewnieniem się, że nie złapiesz żadnych złych nawyków, jeśli chcesz zrobić karierę ???

PAMIĘTAJ: możesz użyć wyliczenia i ustawić, aby używał wartości dziesiętnych, ponieważ dziesiętny jest typem wartości, co spełnia kryteria tego, czego wymaga wyliczenie. Ponieważ enum jest zdefiniowane w strukturze .Net jako typ wartości, więc można ustawiać tylko typy wartości, takie jak typy oparte na liczbach, aby utworzyć typ wyliczeniowy w niestandardowych klasach kodów. Po prostu dołącz każdą wartość z nazwą lub jakimś rodzajem użytym powyżej, np. Nad wagą i itp. I upewnij się, że każdy wpis w wyliczeniu ma logiczną kolejność do niego. tzn. wpisy pod względem wartości dziesiętnych mają wyraźną definicję przejścia w górę lub w dół. Po skonfigurowaniu enum utwórz zmienną typu enum, który właśnie utworzyłeś, a następnie podaj tę zmienną do przełącznika.

Baw się dobrze.

Powiązane problemy