﻿# V3153\. Dereferencing the result of null\-conditional access operator can lead to NullReferenceException\.

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

Разыменование может произойти в нескольких случаях:

* после условного доступа к потенциально нулевому элементу результат null\-conditional оператора взяли в скобки перед дальнейшим разыменованием;
* в перечислимом выражении в 'foreach' используется оператор условного доступа\.

Сценарии выше могут привести к:

1. Возникновению ошибки, если ссылка, по которой осуществлялся условный доступ, имеет значение 'null'\.
1. Корректной работе программы, так как ссылка, по которой осуществлялся условный доступ, всегда не равна 'null'\. В этом случае такая проверка является лишней\.

Рассмотрим первый вариант\. Здесь может возникнуть исключение:

```cpp
var t = (obj?.ToString()).GetHashCode();
```

Если объект 'obj' окажется равен 'null', то в выражении 'obj?\.ToString\(\)' метод 'ToString\(\)' не будет вызван\. Это принцип работы оператора условного доступа\. Но метод 'GetHashCode\(\)' всё равно будет вызван, поскольку его вызов уже не будет относиться к оператору условного доступа\.

Исправленный вариант кода:

```cpp
var t = obj?.ToString().GetHashCode();
```

Здесь, кроме отсутствия опасного разыменования, переменная 't' теперь будет иметь тип 'Nullable<int\>', что корректно отражает её содержимое как потенциально содержащее значение 'null'\.

Рассмотрим теперь случай, когда разыменование безопасное, а проверка лишняя:

```cpp
object obj = GetNotNullString();
....
var t = ((obj as String)?.Length).GetHashCode();
```

Этот код всегда работает корректно\. Объект 'obj' всегда имеет тип 'String', а значит проверка после приведения типа избыточна\.

Исправленный вариант:

```cpp
var t = ((String)obj).Length.GetHashCode();
```

Рассмотрим пример с циклом 'foreach':

```cpp
void DoSomething(string[] args)
{
  foreach (var str in args?.Where(arg => arg != null))
    ....
}
```

В данном случае, если параметр 'args' равен 'null', то результат выражения 'args?\.Where\(\.\.\.\.\)' также будет равен 'null' из\-за оператора '?\.'\. В таком случае будет выброшено исключение типа 'NullReferenceException' при попытке перебора коллекции в 'foreach'\. Это произойдёт из\-за того, что у результата выражения 'args?\.Where\(\.\.\.\.\)' неявно будет вызван метод 'GetEnumerator\(\)', что приведет к разыменованию нулевой ссылки\.

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

```cpp
void DoSomething(string[] args)
{
  foreach (var str in    args?.Where(arg => arg != null)
                      ?? Enumerable.Empty<string>())
    ....
}
```