Использование десятичных диапазонов в переключателе невозможно в C #? - PullRequest
18 голосов
/ 30 мая 2010

Я только начинаю изучать C # и застрял в чем-то очень простом.

Для моего первого «приложения» я решил пойти на что-то простое, поэтому я решил использовать калькулятор ИМТ.

ИМТ рассчитывается как десятичный тип, который я сейчас пытаюсь использовать в операторе switch, но, по-видимому, десятичный нельзя использовать в переключателе?

Каким было бы решение C # для этого:

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

Ответы [ 5 ]

14 голосов
/ 30 мая 2010

Оператор switch поддерживает только целочисленные типы (перечисления не перечислены, но могут использоваться с операторами switch, поскольку они поддерживаются целочисленным типом) (строки также поддерживаются, как указано в Перевертывание - см. Комментарий для справки) и сравнения равенства с постоянными значениями. Поэтому вы должны использовать несколько 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";
}

Кстати, ваш оператор switch немного устарел, потому что вы переключаетесь с «меньше» на «больше» и используете сквозной режим без перерывов. Я думаю, что нужно использовать только один тип сравнения, чтобы сделать код более легким для понимания или изменения порядка проверок и не использовать провал.

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.
}
9 голосов
/ 30 мая 2010

Это невозможно с switch инструкциями в C #.
Причина в том, что каждый оператор case требует постоянного выражения после него.

Также каждое значение допускается только один раз, и тип выражения должен соответствовать типу в вашем switch. В вашем случае это не так, потому что вы хотели иметь операторы типа bool * case, но десятичные в вашем switch.

Рассмотрите возможность рефакторинга с использованием вспомогательной функции:

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

Дополнительная информация:

Мало того, что значения диапазона не допускаются, но также не допускаются неконстантные выражения.

Вот пример чего-то, что невозможно:

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

Однако это возможно:

bool b = true;
const bool y = false;
switch (b)
{
    case true:
        break;
    case y:
        break;
}
1 голос
/ 30 мая 2010

Ваш дальнейший раздел чтения,

С коммутаторами

можно работать только со значениями или случаями, когда входное значение является постоянным значением, которое коммутатор может выглядеть как индекс и выполнять прикрепленный код, определенный внутри регистра, регистра или регистра, независимо от того, что все используется взаимозаменяемо.

Измените y на true в первом примере, и переключатель должен работать на 'b'.

Второй пример работает, потому что во втором случае используется постоянное или постоянное значение. Поэтому вы соответствуете основным критериям или тому, что нужно для переключения. Хотя многие здесь наверняка скажут вам не кодировать, как это. Включите простое постоянное значение и убедитесь, что ваш коммутатор точно учитывает каждое из различных значений, которое может быть предоставлена ​​вашей предоставленной переменной.

Попробуйте использовать enum, чтобы ваш код соответствовал стандартным практикам кодирования .Net, этот комментарий также соответствует тому, что вы не забираете вредных привычек, если хотите сделать карьеру из этого ???

ПОМНИТЕ: что вы можете использовать перечисление и настроить его на использование десятичных значений, поскольку десятичное число является типом значения, так что это соответствует критериям того, что требуется перечислению. Поскольку enum определен в .Net framework как тип значения, поэтому для создания типа enum в ваших пользовательских классах кода можно настроить только типы значений, такие как основанные на числах типы. Просто прикрепите каждое значение с именем или каким-либо видом, который вы использовали выше, например, с избыточным весом и т. Д., И убедитесь, что каждая запись в перечислении имеет логический порядок. то есть записи в терминах десятичных значений имеют четкое определение повышения или понижения. После того, как ваш enum настроен, создайте переменную типа enum, который вы только что создали, и затем предоставьте эту переменную вашему коммутатору.

Веселого обучения.

0 голосов
/ 30 мая 2010

Ключевое слово switch отлично работает с десятичными числами. Это <и> доставляют вам неприятности.

0 голосов
/ 30 мая 2010

Вы также можете использовать какую-то коллекцию, в которой хранятся предельные значения и описания. (Я не эксперт по C # ... может быть Dictionary<decimal,string>?) Итерируйте его, чтобы найти последний, который меньше вашего bmi, и верните соответствующий ему ярлык.

...