Анализатор обнаружил потенциальную ошибку, которая может привести к доступу по нулевой ссылке.
Анализатор заметил в коде следующую ситуацию. Сначала объект проверяется на null, а потом используется уже без проверки на null. Это может означать одно из двух:
1) Возникнет исключение, если объект будет равен null.
2) Программа всегда работает корректно, так как объект всегда не равен null. Проверка является лишней.
Рассмотрим первый вариант. Здесь может возникнуть исключение.
obj = Foo();
if (obj != null)
obj.Func1();
obj.Func2();
Если объект 'obj' окажется равен null, то выражение 'obj.Func2()' приведёт к ошибке. Анализатор выдаст предупреждение на этот код, указав 2 строки. Первая строка - это то место, где используется объект. Вторая строка - это то место, где объект сравнивается со значением null.
Исправленный вариант кода:
obj = Foo();
if (obj != null) {
obj.Func1();
obj.Func2();
}
Рассмотрим второй вариант. Проход по списку безопасный, проверка лишняя
List<string> list = CreateNotEmptyList();
if (list == null || list.Count == 0) { .... }
foreach (string item in list) { .... }
Этот код всегда работает корректно. Список list всегда не пуст. Однако анализатор не разобрался в этой ситуации и выдал предупреждение. Чтобы оно исчезло, следует удалить проверку "if (list == null || list.Count == 0)". Она не имеет практического смысла и может только запутать программиста, читающего код.
Исправленный вариант:
List<string> list = CreateNotEmptyList();
foreach (string item in list) { .... }
Ещё один вариант сообщения анализатора - когда проверка и использование расположены в разных ветках if\else или switch выражений. Например:
if (lines.Count == 1)
{
if (obj != null)
obj.Func1();
}
else
{
lines.Clear();
obj.Func2();
}
В такой ситуации, несмотря на то, что обе ветки никогда не выполнятся одновременно, а будет выбрана только одна из веток, проверка на null в одной из них косвенно свидетельствует о возможности принятия переменной значения null и в другой ветке. Тогда, если управление придёт во вторую ветку, возникнет исключение.
Исправленный вариант:
if (lines.Count == 1)
{
if (obj != null)
obj.Func1();
}
else
{
lines.Clear();
if (obj != null)
obj.Func2();
}
В случае если анализатор ошибается, то кроме изменения кода, можно использовать комментарий для подавления предупреждений. Пример: "obj.Foo(); //-V3125".
Данная диагностика классифицируется как:
Взгляните на примеры ошибок, обнаруженных с помощью диагностики V3125. |