Вопрос немного неясен, но я попробую.
Прежде всего, ответ Адама верен, поскольку существует разница в IL, которую компилятор генерирует в зависимости от того, включен или выключен переключатель "оптимизировать". Компилятор гораздо агрессивнее удаляет недоступный код при включенном оптимизаторе.
Существует два вида недоступного кода, которые имеют отношение к делу. Сначала есть де-юре недоступный код; то есть код, который спецификация языка C # вызывает как недостижимый . Во-вторых, существует де-факто недоступный код; это код, который спецификация C # не вызывает как недоступный, но, тем не менее, не может быть достигнут. Из последнего типа недоступного кода есть код, который известен оптимизатору как недоступный, и есть код , неизвестный оптимизатору , чтобы быть недоступным.
Компилятор обычно всегда удаляет де-юре недоступный код, но удаляет де-факто недоступный код, если оптимизатор включен.
Вот пример каждого из них:
int x = 123;
int y = 0;
if (false) Console.WriteLine(1);
if (x * 0 != 0) Console.WriteLine(2);
if (x * y != 0) Console.WriteLine(3);
Все три строки Console.WriteLine недоступны. Первый - де-юре недоступен; компилятор C # утверждает, что этот код должен рассматриваться как недоступный для целей проверки определенного присваивания.
Вторые два де-юре достижимы, но де-факто недоступны. Они должны быть проверены на наличие определенных ошибок присваивания, но оптимизатору разрешено их удалять.
Из этих двух оптимизатор обнаруживает случай (2), но не случай (3). Оптимизатор знает, что целое число, умноженное на ноль, всегда равно нулю, и поэтому условие всегда ложно, поэтому он удаляет весь оператор.
В (3) случае оптимизатор не отслеживает возможные значения, назначенные y, и определяет, что y всегда равно нулю в точке умножения. Даже если вы и я знаем, что последствия недостижимы, оптимизатор этого не знает.
Бит о проверке определенного присваивания выглядит следующим образом: если у вас недостижимый оператор, то все локальные переменные считаются назначенными в этом операторе, а все назначения считаются несуществующими:
int z;
if (false) z = 123;
Console.WriteLine(z); // Error
if (false) Console.WriteLine(z); // Legal
Первое использование недопустимо, поскольку z не было определенно назначено при его использовании. Второе использование не незаконно, потому что код даже недоступен; z нельзя использовать до того, как он назначен, потому что управление никогда не попадет туда!
В C # 2 были некоторые ошибки, которые смешивали два вида достижимости. В C # 2 вы можете сделать это:
int x = 123;
int z;
if (x * 0 != 0) Console.WriteLine(z);
И компилятор не будет жаловаться, даже если de jure вызов Console.WriteLine достижим. Я исправил это в C # 3.0, и мы взяли последние изменения.
Обратите внимание, что мы оставляем за собой право в любое время изменить работу недоступного детектора кода и генератора кода; мы могли бы решить всегда испускать недоступный код или никогда не испускать его или что-то еще.