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

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

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

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

Фиксация была чем-то вроде этого:

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

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

Но это не делает! Нет никаких предупреждений на той части кода, и я не могу выяснить почему. Какие-либо идеи?

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

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

или

try { ... } catch { }
18
задан Cristi Diaconescu 29 April 2010 в 21:27
поделиться

7 ответов

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

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

Как вы это себе представляете?

Что ж, рассмотрим следующее.

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

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

DoIt(); // discard the return value

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

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

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

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

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

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

25
ответ дан 30 November 2019 в 07:17
поделиться

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

1
ответ дан 30 November 2019 в 07:17
поделиться

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

1
ответ дан 30 November 2019 в 07:17
поделиться

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

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

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

1
ответ дан 30 November 2019 в 07:17
поделиться

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

9
ответ дан 30 November 2019 в 07:17
поделиться

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

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

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

0
ответ дан 30 November 2019 в 07:17
поделиться

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

1
ответ дан 30 November 2019 в 07:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: