Подтвердить что ты не робот

Объявления переменных после операторов if

Проблема возникла на другом форуме, и я знал, как ее исправить, но она показала особенность компилятора, свойственного мне. У человека возникла ошибка: "Встроенный оператор не может быть объявлением или помеченной инструкцией", потому что у них было объявление переменной, следующей за оператором if без скобок. Это не было их целью, но они прокомментировали строку кода, непосредственно следуя за оператором if, что сделало объявление переменной фактической строкой кода для выполнения. Во всяком случае, тот фон, который подводит меня к этому.

Следующий код является незаконным

if (true)
    int i = 7;

Однако, если вы скопируете это в скобки, все это будет законным.

if (true)
{
    int i = 7;
}

Ни одна часть кода не полезна. Но второй - в порядке. Что конкретно объясняет такое поведение?

4b9b3361

Ответ 1

спецификация языка С# различает три типа операторов (подробнее см. главу 8). В общем, вы можете иметь следующие утверждения:

  • labeled-statement - я предполагаю, что это для старомодного оператора goto
  • statement-statement - это объявление переменной
  • embedded-statement - который содержит почти все остальные утверждения

В операторе if тело должно быть встроенным-выражением, что объясняет, почему первая версия кода не работает. Вот синтаксис if из спецификации (раздел 8.7.1):

if (boolean-expression) embedded-statement
if (boolean-expression) embedded-statement else embedded-statement

Объявление переменной - выражение-выражение, поэтому оно не может появляться в теле. Если вы заключите объявление в скобки, вы получите блок операторов, который является встроенным оператором (и поэтому он может появиться в этой позиции).

Ответ 2

Если вы не включаете скобки, она выполняет следующую строку, как если бы она была окружена скобками. Так как не имеет смысла объявлять переменную в этой строке (вы никогда не сможете ее использовать), компилятор С# не позволит этому предотвратить случайное выполнение этого действия, не зная (что может привести к тонким ошибкам).

Здесь часть Эрика Липперта должна сказать о компиляторе С# на этом SO ответе о разрешении имени:

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

Ответ 3

Все компиляторы позволят вам скомпилировать код, который является бесполезным или чрезвычайно низким. Существует слишком много способов, которыми разработчик может использовать язык для создания конструкций без необходимости. Укомплектовать компилятором все это просто слишком много усилий и, как правило, не стоит.

Второй случай вызывается непосредственно в спецификации языка С# в начале раздела 8.0

Пример приводит к ошибке времени компиляции, поскольку для оператора if требуется встроенный оператор, а не оператор для ветки if. Если бы этот код был разрешен, тогда переменная я была бы объявлена, но никогда не использовалась. Обратите внимание, однако, что путем размещения объявления в блоке, пример действителен.

Пример кода

void F(bool b) {
    if (b)
        int i = 44;
}

Ответ 4

Добавление закрывающих и открывающих фигурных скобок в другой части if помогло мне, как я сделал ниже, в отличие от того, что я делал, прежде чем добавлять их;

До: это вызвало ошибку:

protected void btnAdd_Click(object sender, EventArgs e)
    {
        if (btnAdd.Text == "ADD")
        {

            CATEGORY cat = new CATEGORY
            {

                NAME = tbxCategory.Text.Trim(),
                TOTALSALEVALUE = tbxSaleValue.Text.Trim(),
                PROFIT = tbxProfit.Text.Trim()

            };
            dm.AddCategory(cat, tbxCategory.Text.Trim());
        }
        else
        // missing brackets - this was causing the error
            var c = getCategory();
            c.NAME = tbxCategory.Text.Trim();
            c.TOTALSALEVALUE = tbxSaleValue.Text.Trim();
            c.PROFIT = tbxProfit.Text.Trim();
            dm.UpdateCategory(c);

        btnSearchCat_Click(btnSearchCat, e);
    }

После: Добавлены скобки в ветке else

protected void btnAdd_Click(object sender, EventArgs e)
    {
        if (btnAdd.Text == "ADD")
        {

            CATEGORY cat = new CATEGORY
            {

                NAME = tbxCategory.Text.Trim(),
                TOTALSALEVALUE = tbxSaleValue.Text.Trim(),
                PROFIT = tbxProfit.Text.Trim()

            };
            dm.AddCategory(cat, tbxCategory.Text.Trim());
        }
        else
        {
            var c = getCategory();
            c.NAME = tbxCategory.Text.Trim();
            c.TOTALSALEVALUE = tbxSaleValue.Text.Trim();
            c.PROFIT = tbxProfit.Text.Trim();
            dm.UpdateCategory(c);
        }
        btnSearchCat_Click(btnSearchCat, e);
    }