# 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.

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

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

    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'.

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

CWE-783

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