Анализатор обнаружил фрагмент кода, который, скорее всего, содержит логическую ошибку. В тексте программы имеется выражение, содержащее оператор '??' или '?:', которое может вычисляться не так, как планировал программист.
Операторы '??' и '?:' имеют более низкий приоритет по сравнению с операторами ||, &&, |, ^, &, !=, ==, +, -, %, /, *. Это можно случайно забыть и написать ошибочный код, подобный приведенному ниже:
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. |