Вопрос по boolean, switch-statement, c#, .net – Странное поведение регистра переключателя с логическим значением

3

Мой вопрос не о том, как решить эту ошибку (я уже решил ее), а о том, почему эта ошибка имеет логическое значение.

Моя функция

private string NumberToString(int number, bool flag)
{
    string str;

    switch(flag)
    {
        case true: 
            str = number.ToString("00");
            break;
        case false:
            str = number.ToString("0000"); 
            break;
    }

    return str;
}

ОшибкаUse of unassigned local variable 'str', Bool может принимать только истину или ложь. Так будет заселятьсяstr в любом случае. Тогда почему эта ошибка?

Более того, эта ошибка исчезнет, если наряду с истинным и ложным регистром я добавлюdefault случай, но все же, что может bool держать отдельно от истины и лжи?

Почему это странное поведение с переменной bool?

Возможноnull Похожеbool? flag = null; Bali C
Тот же вопрос задавался раньше, сейчас ищем дубликат. leppie
Я не думаю, что компилятор учитывает возможные значения типа при проверке определенного присваивания внутриswitch заявление. Другими словами, вы получите ту же ошибку, еслиflag былint а у тебя 4 294 967 296case заявления в диапазоне от-2,147,483,648 в2,147,483,647. Frédéric Hamidi
Это ошибка во время выполнения, ошибка компиляции или предупреждение? Попробуйте строку str = ""; Oliver Kötter
@ Ollie: ошибка компилятора. leppie

Ваш Ответ

5   ответов
4

strеременная @ не назначена, так как регистр оператора switch будет присваивать ей какое-либо значение, но компилятор не может определить, попадет ли он в какой-либо из операторов case, поэтому вы получаете эту ошибку при возвратеstr.

Если вы добавите регистр по умолчанию со строковым присваиванием, то компилятор точно будет знать, что str будет содержать некоторое значение, и поэтому вы не получите ошибку

yes, но компилятор C # не принимает это во внимание, я пытаюсь найти официальный источник для этого, опубликую его, как только найду Habib
Я думаю, что Тим Шмельтер только что опубликовал это. stackoverflow.com/a/8933935/28424 Nikhil Agrawal
Но bool всегда содержит значение, так как это тип значения. Nikhil Agrawal
6

string переменная ин boolean возможные значения.

Тот факт, что естьни за чт что никто изcases run, это правда (в данном случае), но компилятор не заходит так далеко при анализе кода. Он просто смотрит на переменную, которая не присваивается и не используется в некоторых условиях, а не по умолчанию, поэтому Предположим что таммо будет случай, когда он останется неназначенным.

+ 1. Похоже, это то, что я ищу. Nikhil Agrawal
9

бесполезным. Почему бы не использовать условный оператор ?:):

pri,vate string NumberToString(int number, bool flag)
{
    return flag ? number.ToString("00") : number.ToString("0000"); 
}

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

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

Что, если в корпусе коммутатора было больше строк кода? То, что вы предоставили, является альтернативой, а не объяснением причины. Nikhil Agrawal
Вы сказали, что назначение не должно происходить внутри условных выражений. Правильно? Неправильно. Добавьте условный оператор по умолчанию, и он не выдаст ошибку. Nikhil Agrawal
Да, добавление оператора case по умолчанию действительно исправит ошибку. Но, как я уже сказал, написание оператора switch с вариантами true, false и default кажется абсолютно безумным и хорошим кандидатом на thedailywtf.com: -) Darin Dimitrov
@ NikhilAgrawal: Это должно быть максимально простым для компилятора, а также для предотвращения простых ошибок программиста. Поэтому, если вы покажете, что немного подумали об этом (случай по умолчанию), компилятор разрешит это. Rango
Или еще лучше:return number.ToString(flag ? "00" : "0000"):) nawfal
3
private string NumberToString(int number, bool flag)
{
    string str = "";

    switch(flag)
    {
        case true: 
            str = number.ToString("00");
            break;
        case false:
            str = number.ToString("0000"); 
            break;
    }

    return str;
}

напиши это string str = ""; - вам следует присвоить значение

Если вы добавляете регистр по умолчанию, нет шанса пролистать регистр переключателя без назначения. Теперь эт

0

есть хорошее объяснение причин этой проблемы, но есть еще одно решение проблемы, которое не было упомянуто. Просто поставьdefault вместо второгоcase:

    private string NumberToString(int number, bool flag)
    {
        string str;

        switch (flag)
        {
            case true:
                str = number.ToString("00");
                break;
            default:
                str = number.ToString("0000");
                break;
        }

        return str;
    }

У компилятора больше нет мыслей оflag значение переменной, поскольку мы всегда присваиваемdefault значение в нашемswitch заявление

Также рассмотрим эквивалентное решение оператора if-else:

    private string NumberToString(int number, bool flag)
    {
        string str;

        if (flag)
            str = number.ToString("00");
        else
            str = number.ToString("0000");

        return str;
    }

Мне не особенно нравятся «однострочные» (однострочные решения), так как им не хватает расширяемости и, кроме того, читабельности, но в качестве последнего средства просто используйте троичные операторы, подобные этому:

    private string NumberToString(int number, bool flag)
    {
        return flag ? number.ToString("00") : number.ToString("0000");
    }

Пока я занимаюсь этим - рассмотрите возможность использования метода расширения + значение по умолчанию, равноеfalse, например

public static class intExtensions
{
    public static string NumberToString(this int number, bool flag = false)
    {
        return flag ? number.ToString("00") : number.ToString("0000");
    }
}

а потом в основной класс:

        int intVal = 56;
        string strVal1 = intVal.NumberToString(true);
        string strVal2 = intVal.NumberToString();

Похожие вопросы