В чем разница и почему Switch Case работает так на С#?

У меня есть две функции, их можно скомпилировать, а другую - нет. В чем разница?

Означает ли функция номер 1, что случай 1 всегда будет удален, или это просто проблема с компилятором?

public void Test(int x)
{
    switch (x)
    {
        case 1:
            uint cId = (uint)3;
            break;

        case 2:
            cId = (uint)5; //NO ERROR HERE. WHY?
            break;
    }
}

public void DeclaringInsideSwitch(int x)
{
    uint tst = 0;
    switch (x)
    {
        case 1:
            int y = 3;
            uint variable = tst;
            break;

        case 2:
            variable++; //ERROR HERE. WHY?
            break;
    }
}

Я, конечно же, искал "Объявлять переменные внутри случая переключения в С#", но для меня это просто похоже на некоторую ошибку в С#, теперь сохраненную для обратной совместимости.

//Получив предупреждение о том, что он уже был дан ответ, мой вопрос теперь может быть сведен к тому, о чем он идет.

Зачем:

int x;
x++;

не работает ли это?

Ответы

Ответ 1

Ну, uint cId определяется в {...} сферы, которая находится в вашем случае switch scope

switch (x)
{
    case 1:
        uint cId = (uint)3; // <- definition 
        break;

    case 2:
        // cId has been defined and thus can be assigned (initialization)
        cId = (uint)5; //NO ERROR HERE WHY?
        break;
}  // <- end of cId scope

Во втором случае variable определена, но перед ее использованием (приращением) должна быть инициализирована локальная переменная:

switch (x)
{
    case 1:
        int y = 3;
        uint variable = tst; // <- definition 
        break;
    case 2:
        // variable defined, but has not been initialized ("case 1:" hasn't been run),
        // variable contains trash and so you can't increment it 
        variable++; //ERROR HERE WHY?
        break;
} // <- end of variable scope

Ответ 2

В принципе, объявление переменной значительно шире, чем вы думаете; второй пример страдает от "определенного назначения", поскольку он объявлен (шире), но фактически не назначен, поэтому ++ не имеет смысла в неназначенном значении.

Если вы хотите, чтобы в каждом case, вы можете сделать это... просто добавьте фигурные скобки:

        switch (x)
        {
            case 1:
            {
                uint cId = (uint)3;
                break;
            }
            case 2:
            {
                uint cId = (uint)5;
                break;
            }
        }

Это немного досадно? Да. Это антиинтуитивно? Да. Будет ли это когда-либо изменено? Маловероятно, так как это было бы значительным изменением, которое остановило бы многие существующие С# из компиляции.