>
>
>
V3125. The object was used after it was…


V3125. The object was used after it was verified against null. Check lines: N1, N2.

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

Анализатор заметил в коде следующую ситуацию. Сначала объект проверяется на 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.