Тип значения (структура):
При реализации IEquatable для пользовательского значения type (struct), мы склонны писать подход, который я выбрал, увидев некоторые реализации в нескольких моих предыдущих организациях и несколько сообщений в Интернете, фактическую логику равенства в реализации метода Equals(Tother) и для достижения согласованность:
- переопределить метод Equals(Object? obj) и
- перегрузки == & != оператор
Код: Выделить всё
public readonly struct CommandKey : IEquatable
{
public String Key { get; }
public CommandKey(String key)
{
Key = key;
}
//Actual equality logic here
public Boolean Equals(CommandKey other) => String.Equals(Key, other.Key);
//Compatibility with Object.Equals
public override Boolean Equals(Object? obj) => obj is not null && obj is CommandKey other && Equals(other);
//Consistent hash code
public override Int32 GetHashCode() => Key.GetHashCode();
//Operator overloads
public static Boolean operator ==(CommandKey left, CommandKey right) => left.Equals(right);
public static Boolean operator !=(CommandKey left, CommandKey right) => !left.Equals(right);
}
И аналогично для ссылочного типа (класса): мы склонны напишите логику равенства в перегрузке оператора == и для достижения согласованности:
- override Equals(Object? obj) метод
- реализовать IEquatable.Equals(T другой) метод и
- перегрузить оператор !=
Код: Выделить всё
public sealed class CommandRequest : IEquatable
{
public CommandKey CommandKey { get; }
//there are other properties as well
public Boolean Equals(CommandRequest? other) => this == other;
public override Boolean Equals(Object? obj) => obj is not null && obj is CommandRequest other && Equals(other);
public static Boolean operator ==(CommandRequest? left, CommandRequest? right)
{
if (ReferenceEquals(left, right))
{
return true;
}
if (left is null || right is null)
{
return false;
}
return
left.CommandKey == right.CommandKey &&
//other properties;
}
public static Boolean operator !=(CommandRequest? left, CommandRequest? right) => !(left == right);
}
Другая причина Я могу подумать, что для ссылочного типа нужно написать логику равенства в перегрузке оператора ==, если один из объектов имеет значение null, скажем, например:
Код: Выделить всё
ClassA a = null;
ClassB b = new ClassB();
a.Equals(b); //compiles successfully but during runtime, throws System.NullReferenceException
Вопрос
Для пользовательских типов значений , какова причина написания фактической логики равенства в реализации метода Equals(Tother), а не в перегрузке оператора ==?Для структуры я могу поместить логику в Equals(T другой) метод IEquatable, а затем вызвать его из других методов и операторов для согласованности.
Для класса, где следует разместить логику проверки равенства (независимо от того, равенство ли это значению или ссылке) и почему?
Подробнее здесь: https://stackoverflow.com/questions/792 ... r-overload