Unicorn with delicious cookie
Мы используем куки, чтобы пользоваться сайтом было удобно.
Хорошо
to the top
>
>
>
V3123. Perhaps the '??' operator...
menu mobile close menu
Проверка проектов
Дополнительная информация
toggle menu Оглавление

V3123. Perhaps the '??' operator works in a different way than it was expected. Its priority is lower than priority of other operators in its left part.

12 Дек 2016

Анализатор обнаружил фрагмент кода, который, скорее всего, содержит логическую ошибку. В тексте программы имеется выражение, содержащее оператор '??' или '?:', которое может вычисляться не так, как планировал программист.

Операторы '??' и '?:' имеют более низкий приоритет по сравнению с операторами ||, &&, |, ^, &, !=, ==, +, -, %, /, *. Это можно случайно забыть и написать ошибочный код, подобный приведенному ниже:

public bool Equals(Edit<TNode> other)
{
    return _kind == other._kind
        && (_node == null) ? other._node == null :
                             node.Equals(other._node);
}

Так как приоритет оператора '&&' выше чем оператора '?:', то сначала будет выполнено выражение '_kind == other._kind && (_node == null)'. Чтобы избежать таких ошибок, следует заключать всё выражение, содержащее оператор '?:', в скобки:

public bool Equals(Edit<TNode> other)
{
    return _kind == other._kind
        && ((_node == null) ? other._node == null :
                              node.Equals(other._node));
}

Рассмотрим другой пример с оператором '??':

public override int GetHashCode()
{
    return ValueTypes.Aggregate(...)
         ^ IndexMap?.Aggregate(...) ?? 0;
}

Приоритет оператора '^' выше чем приоритет оператора '??', поэтому если 'IndexMap' равен 'null', то и левая часть оператора '??' тоже будет иметь значение 'null', и значит функция всегда будет возвращать 0 вне зависимости от того что содержится в коллекции 'ValueTypes'.

Как и в случае оператора '?:', выражение с оператором '??' лучше заключать в скобки

public override int GetHashCode()
{
    return ValueTypes.Aggregate(...)
         ^ (IndexMap?.Aggregate(...) ?? 0);
}

Теперь функция 'GetHashCode()' будет возвращать разные значения в зависимости от содержимого коллекции 'ValueTypes' и в том случае когда 'IndexMap' будет равен 'null'.

Данная диагностика классифицируется как:

Взгляните на примеры ошибок, обнаруженных с помощью диагностики V3123.