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

Компилятор С# должен давать предупреждение, но не так ли?

Кто-то из моей команды попытался исправить предупреждение "переменная не используется" в предложении пустой catch.

try { ... } catch (Exception ex) { }

- > дает предупреждение о том, что ex не используется. Пока что так хорошо.

Исправление было примерно таким:

try { ... } catch (Exception ex) { string s = ex.Message; }

Увидев это, я подумал: "Отлично, теперь компилятор будет жаловаться на s, который не используется."

Но это не так! На этом фрагменте кода нет предупреждений, и я не могу понять, почему. Любые идеи?

PS. Я знаю, что все пункты, которые запрещают исключения, - это плохая вещь, но это другая тема. Я также знаю, что первоначальное предупреждение лучше удаляется, делая что-то вроде этого, это тоже не так.

try { ... } catch (Exception) { }

или

try { ... } catch { }
4b9b3361

Ответ 1

В этом случае компилятор обнаруживает, что s написан, но не прочитан, а намеренно подавляет предупреждение.

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

Как вы это понимаете?

Хорошо, рассмотрим следующее.

У вас есть программа, которая вызывает метод DoIt(), который возвращает строку. У вас нет исходного кода для DoIt(), но вы хотите проверить в отладчике, каково его возвращаемое значение.

Теперь в вашем конкретном случае вы используете DoIt() для своих побочных эффектов, а не его возвращаемое значение. Итак, вы говорите

DoIt(); // discard the return value

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

И на самом деле управляемый отладчик не имеет возможности "смотреть на вещь, возвращенную предыдущим вызовом метода". Неуправляемый отладчик С++ имеет эту функцию, потому что он может смотреть на регистр EAX, где отбрасывается возвращаемое значение, но у вас нет гарантии в управляемом коде, что возвращаемое значение все еще живое, если оно было отброшено.

Теперь можно утверждать, что это полезная функция, и команда отладчика должна добавить функцию, в которой возвращаемые значения сохраняются в живых, если точка останова отладчика сразу же после выполнения метода. Это было бы неплохой особенностью, но я не тот человек, который просил об этом; go спросите команду отладчика.

Что нужно сделать разработчику с низким уровнем С#? Создайте локальную переменную, сохраните результат в локальной переменной и затем изучите локальную часть в отладчике. Отладчик действительно гарантирует, что локальные жители не будут собирать мусор агрессивно.

Итак, вы делаете это, а затем компилятор дает вам предупреждение о том, что у вас есть локальный, который только написан и никогда не читается, потому что предмет, выполняющий чтение, не является частью программы, это разработчик, сидящий там, наблюдая за отладчик. Это очень раздражает пользователя! Поэтому мы обнаруживаем ситуацию, когда непостоянное значение присваивается локальной переменной или полю, которое никогда не читается, и подавляйте это предупреждение. Если вы измените свой код, чтобы вместо него было написано string s = "hello";, вы начнете получать предупреждение, потому что причина компилятора, ну, возможно, это не может быть кто-то, кто работает с ограничениями отладчика, потому что это значение прямо там, где он может быть прочитан разработчиком уже без отладчика.

Это объясняет это. Существует множество других случаев, когда мы подавляем предупреждения о переменных, которые никогда не читаются; a подробный экзегетик всех политик компилятора, когда мы сообщаем о предупреждениях, и когда мы не займем мне достаточно времени, чтобы написать, так что я думаю Я оставлю это при этом.

Ответ 2

Переменная s используется... для хранения ссылки на ex.Message. Если у вас есть только строка s; вы получите предупреждение.

Ответ 3

Я думаю, что человеку, который отвечает на это, потребуется некоторое представление о том, как работает компилятор. Однако что-то вроде FxCop, вероятно, поймает это.

Ответ 4

Свойства - это просто методы, и ничто не мешает кому-либо помещать некоторый код, который что-то делает в свойстве ex.Message. Поэтому, хотя вы, возможно, не делаете ничего с s, вызывая ex.Message COULD потенциально имеющую ценность....

Ответ 5

На самом деле компилятор не выполняет работу над каждым экземпляром и угловым случаем, когда переменная может использоваться или не использоваться. Некоторые из них легко обнаружить, некоторые из них более проблематичны. Erring на стороне осторожности - это разумная вещь (особенно, когда предупреждения могут быть установлены как ошибки), представьте, если программное обеспечение не скомпилировалось только потому, что компилятор думал, что вы не используете что-то, что вы были). Команда компилятора Microsoft специально говорит:

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

- Эд Маурер, руководитель разработки, управляемая платформа компилятора

Ответ 6

Resharper поймает, что

Ответ 7

Статический анализ несколько ограничен в том, что он может выполнить сегодня. (Хотя, как заметил Эрик, не потому, что в этом случае он не знает.)

Новые кодовые контракты в .NET 4 значительно улучшают статическую проверку, и в один прекрасный день я уверен, что вы получите больше помощи с очевидными ошибками.

Если вы пробовали Code Contracts, вы, однако, знаете, что сделать исчерпывающий статический анализ вашего кода непросто - он может трэш в течение нескольких минут после каждого компиляции. Статический анализ всегда сможет найти любую проблему, подобную этой, во время компиляции? Вероятно, нет: см. http://en.wikipedia.org/wiki/Halting_problem.