Expression.Equal решение, которое учитывает перегрузки "Equals" и неявные операторы - PullRequest
0 голосов
/ 01 февраля 2020

При компиляции кода во время выполнения с использованием деревьев выражений нам может понадобиться проверить объекты неопределенных типов на равенство.

Если бы мы просто кодировали это вручную для каждого случая, компилятор во многом для нас. Большинство из них приходят на ум:

  1. Если доступна универсальная c перегрузка T1.Equals<T2> или T2.Equals<T1>, то используется.
  2. В противном случае, если любой из типов имеет неявный оператор, который позволил бы нам применить (1), который используется.
  3. В противном случае используется bool Equals(object) (конечно, с учетом возможных переопределений).

К сожалению, Expression.Equal(Expression left, Expression right) не делает все это за нас.

Как мы можем добиться того же поведения, которое обычно обеспечивает компилятор?

1 Ответ

0 голосов
/ 05 марта 2020

Предполагая, что мы сравниваем только объекты с одинаковыми типами времени компиляции, мы можем следовать простому двухэтапному процессу при построении выражения вызова:

  1. Если тип времени компиляции реализует IEquatable<T>, где T - это сам тип, затем вызовите соответствующий метод Equals(T).

Это предотвращает упаковку в структуры, которые реализуют IEquatable<T>, что они часто делают именно по этой причине. Он имеет дополнительное преимущество, вызывая наиболее очевидную перегрузку Equals для классов.

В противном случае вызовите обычный (возможно переопределенный) метод Equals(object).

Существует два предостережения.

Первое предостережение заключается в том, что Equals(T) методов при отсутствии IEquatable<T> интерфейс игнорируется. Это может считаться разумным: если разработчик не добавил интерфейс, не совсем ясно, хотели ли они, чтобы метод использовался для этой цели или нет.

Второе предостережение заключается в том, что для классов Интерфейс IEquatable<T> в классе base игнорируется, тогда как компилятор мог бы предпочесть перегрузку, соответствующую этому. К счастью, мы можем разумно ожидать, что Equals(object) вернет тот же результат, что и Equals(T) для T объекта. Если нет, разработчик предоставил неоднозначное определение равенства, и все ставки отменены.

...