Почему это компилируется

#c#

#c#

Вопрос:

Мне трудно понять, что означает следующий код (и частично, почему он вообще компилируется).

У нас есть следующий фрагмент:

 if (true) return;
{
    ... // Unreachable code detected
}
  

Почему это вообще компилируется?

Правильно ли я понимаю, что компилятор предполагает else в этой конструкции? Если нет, то как это работает?

Я думаю, что это должно быть логически эквивалентно

 if (true) 
    return;
else
{
    ...; // Unreachable code detected.
}
  

Я сомневаюсь, потому что компилятор, похоже, не интерпретирует следующее как if-else

 if (condition) 
{
    ...
}
{
    ...
}
  

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

Это поведение явно указано в спецификациях C #?

Комментарии:

1. Ваш последний пример НЕ является ошибкой компиляции. Ваши первые два примера также не эквивалентны.

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

3. отредактировал вопрос, чтобы он был (более) конструктивным, и проголосовал за повторное открытие.

4. Я думаю, что OP необходимо отредактировать вопрос, потому что я не уверен, что вы правильно угадали, о чем он спрашивал, в целом; Я думаю, что он также спрашивал, почему «недоступный код» будет компилироваться.

Ответ №1:

Здесь не предполагается else , просто любой код вида:

 if(condition)
{
    code A

    return;
}

code B
  

логически эквивалентно:

 if(condition)
{
    code A

    return;
}
else
{
    code B
}
  

Потому что code B будет достигнуто только в том случае, condition если значение равно false.

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

 code A

{
    code B
}
  

Это совершенно законно; для блоков кода не требуются ключевые слова потока управления, и вы можете поместить свой код в фигурные скобки, где вам нравится. Хотя это не очень распространено, это законно. Обратите внимание, что это создает новую область видимости переменной в вашем коде, и (как и все другие блоки кода) код за пределами этих блоков не сможет получить доступ к любым переменным, объявленным в блоке.

Например:

 code A

{
    int foo = 10;

    code B
}

int bar = foo; // compiler error, as foo is not a variable within this scope
  

Хотя это и не рекомендуется, вы могли бы использовать это для объявления двух переменных с одинаковыми именами, но разных:

 {
    int foo = 10;

    code A
}
{
    string foo = "bar";

    code B
}
  

Комментарии:

1. А? В вашем первом примере код B достижим, независимо от того, что condition решает. Во втором примере код B недоступен, если condition имеет значение staticly false. Итак, в моем примере компилятор предполагает else , иначе для начала не было бы предупреждения о недоступности кода.

2. @InBetween: Нет, это не так. Если condition имеет значение true, то code A будет выполнено, и функция вернется.

3. @AdamRobinson — Я прокомментирую отрицательный отзыв, они глупы, за то, что дали вам отрицательный отзыв о правильном заключении.

4. Я не сторонник снижения. Но оператору (совершенно очевидно) интересно, что { block of code; } означает одинокий (т. Е. С помощью if или else). Этот ответ не распознает это, не говоря уже о том, чтобы обратиться к нему

5. @sehe: Судя по его комментариям, он задавал оба вопроса. Я отредактировал свой ответ, чтобы решить и это (я обратился к нему в комментариях к другому ответу). Спасибо!

Ответ №2:

Ваше замешательство связано с тем фактом, что вы можете включить что угодно в произвольный { } . Например:

 {
    Console.WriteLine(a);
    {
        a = 6;
    }
}
{
    Console.WriteLine(a);
}
  

Это совершенно справедливо, и все фигурные скобки совершенно бессмысленны. Но все еще действует!

Комментарии:

1. Это был бы хороший комментарий. Вероятно, это вся путаница, возникшая в OP

2. Я просто пишу это по частям. Это больше, чем это. 😉

3. @sehe: Это отвечает на вопрос OP; почему это было бы лучше в качестве комментария?

4. @AdamRobinson: главным образом потому, что вопрос был уже закрыт до того, как ответ вырос в пример 🙂 Так что да, я думаю, что любые ответы здесь, скорее всего, были бы хорошими комментариями. Вопрос как таковой был просто некорректным и неконструктивным.

5. @sehe: Кроме того, я только что назначил его для повторного открытия. Я не вижу ничего плохого в этом вопросе.

Ответ №3:

 if (true) return;
{
    ... // Unreachable code detected. WTF?
}
  

эквивалентно

 if (true) 
    return;   
 ... // Unreachable code 
  

здесь больше ничего не подразумевается.

Ответ №4:

Ответьте в комментариях:

 if (true) return;
// whatever is after the previous statement will never be executed
// because the previous statement will always return
{
    // this is not automatically added to the "else" part of the previous if
    // this is just a code block with additional braces, which are not 
    // required but valid.
}
  

Ответ №5:

Код после return недоступен. Условие true всегда, ошибка, true .

Комментарии:

1. ну, ваш ответ верен, но что он отвечает?

2. @sehe Я, вероятно, не понимаю вопроса, но я понял это так, что InBetween оспаривал тот факт, что блок кода после return был недоступен. Как я должен был интерпретировать вопрос?

3. внимательное чтение фрагментов # 1 и # 2 покажет, что OP думал, что ‘голый блок ( {} )’ является незаконным синтаксисом. Следовательно, он спросил о ‘ почему компилятор принимает else

4. @sehe Спасибо, но я все еще не понимаю. Похоже, это один из тех вопросов, который требует небольшого чтения мыслей. Или, возможно, я просто туп сегодня. Неважно!!

Ответ №6:

Это проблема логики, а не синтаксиса. Поэтому компилятор не обнаружит это.

Что касается вашего третьего примера, он нарушает правила (большинства, если не всех) языков программирования, и поэтому компилятор обнаружит это и выдаст ошибку.

Комментарии:

1. Э, какие правила нарушает третий пример? Это законный код C #.

2. Но почему первый пример не нарушает правила. Заключенный в квадратные скобки блок фактически является else предложением if инструкции, но без else инструкции.

3. @InBetween: это фактически else блок. Это не фактически else блок.

4. @InBetween: Вы действительно пытались его скомпилировать? Вы можете создавать произвольно глубокие блоки кода с фигурными скобками. Нет необходимости, чтобы они были связаны с ключевым словом потока управления, таким как if , else , for и т.д.

Ответ №7:

Нет. ‘;’ после вашего if не закрывает истинную часть. Это закрывает все if. Итак, блок после является доступным кодом. Если ваш первый тест не удался. Компилятор не представил else. Вы думаете, что это потому, что это эквивалентно, но на самом деле это не другое.