Рассмотрим этот минимальный воспроизводимый пример.
Point point1 = new Point(1, 2, 3);
Point point2 = new Point(1, 2, 31);
Console.WriteLine(point1 == point2); // True
Console.WriteLine(point1.Equals(point2)); // True
record Point(double X, double Y, double Z)
{
public virtual bool Equals(Point other)
{
return other != null && X == other.X && Y == other.Y;
}
}
Могу ли я переопределить метод ==
с помощью Equals
? Кажется, я тоже (и не только переопределяю .Equals
). Есть ли способ переопределить только один из них?
Для проверки самолетов я бы лучше сделал метод расширения public static bool IsSameXYPlane(this Point source, params Point[] others) { ... }
Для типов записей нет разницы между равенством значений (проверяется с помощью Equals
) и равенством ссылок (проверяется с помощью ==
). Цитируем документацию:
Те же методы и операторы, которые указывают на ссылочное равенство или неравенство в классах (например,
Object.Equals(Object)
и==
), указывают на равенство или неравенство значений в записях.
То есть, переопределяя метод Equals
, вы также меняете поведение ==
, как и ожидалось для записей.
Своеобразным частичным обходным решением было бы добавить свой собственный метод логического равенства, а не переопределять его Equals
. Это позволит вам протестировать эту логику, не меняя поведение ==
, но, конечно, это очень частичное решение — оно не позволит вам использовать эту логику в других классах, которые ожидают переопределения Equals
(например, наборы или словари). :
// Not overriding Equals
public virtual bool LogicallyEquals(Point other)
{
return other != null && X == other.X && Y == other.Y;
}
При использовании типов записей нет разницы между равенством значений (проверено с помощью Equals) и равенством ссылок -> я не думаю, что это технически правильно. Между Equals
и ==
нет разницы, но две записи могут иметь одинаковое «равенство значений» (те же значения полей по сравнению с EqualiytComparer<T>.Default
), но разное «ссылочное равенство» (т.е. ReferenceEquals
).
@IvanPetrov - реализует записи IEquatable<T>
, которые EqualityComparer<T>.Default
затем будут использовать, и в конечном итоге все это приведет к одному и тому же Equals
методу.
@Damien_The_Unbeliever Верно, возможно, мне придется немного уточнить - я имею в виду, что Equals использует EqualityComparer<T>.Default
в каждом поле для конкретного T
поля.
Как вы можете видеть, оператор
==
вызывает методEquals
. Вы также получите ошибку компилятора, если попытаетесь указать==
самостоятельно, поэтому похоже, что невозможно переопределить одно, но не другое.