Допустим, у нас есть следующие простые классы:
abstract class Abc { }
class Bcd : Abc { public int val; }
По умолчанию оператор ==
в экземплярах Bcd
возвращает false в этом примере:
var result_1 = new Bcd() { val = 10 } == new Bcd() { val = 10 };
Итак, следуя указаниям здесь , оператор ==
можно добавить к Bcd
:
class Bcd : Abc
{
public int val;
public bool Equals(Bcd obj)
{
if (Object.ReferenceEquals(obj, null)) return false;
if (Object.ReferenceEquals(obj, this)) return true;
if (obj.GetType() != GetType()) return false;
return obj.val == val;
}
public override bool Equals(object obj) => Equals(obj as Bcd);
public override int GetHashCode() => val.GetHashCode();
public static bool operator ==(Bcd a, Bcd b)
{
if (Object.ReferenceEquals(a, null))
{
if (Object.ReferenceEquals(b, null)) return true;
return false;
}
return a.Equals(b);
}
public static bool operator !=(Bcd a, Bcd b) => !(a == b);
}
А теперь выражение оценивается как истинное:
var result_1 = new Bcd() { val = 10 } == new Bcd() { val = 10 };
Однако я могу захотеть хранить экземпляры Bcd
(и, возможно, другие экземпляры других подклассов Abc
) в переменных, типизированных как Abc
:
Abc a = new Bcd() { val = 10 };
Abc b = new Bcd() { val = 10 };
Теперь это, конечно, вернет false:
var result_2 = a == b;
Один из способов получить желаемое поведение - это также добавить методы равенства в Abc
(даже если это абстрактный класс):
abstract class Abc
{
public bool Equals(Abc obj)
{
if (obj is Bcd && this is Bcd) return (obj as Bcd) == (this as Bcd);
return false;
}
public static bool operator ==(Abc a, Abc b)
{
if (Object.ReferenceEquals(a, null))
{
if (Object.ReferenceEquals(b, null)) return true;
return false;
}
return a.Equals(b);
}
public static bool operator !=(Abc a, Abc b) => !(a == b);
}
Теперь выражение возвращает true
:
Abc a = new Bcd() { val = 10 };
Abc b = new Bcd() { val = 10 };
var result_2 = a == b;
Мой вопрос таков: является ли рекомендуемый подход добавлением оператора равенства (и метода Equals
, оператора !=
и т. Д.) К абстрактному родительскому классу Abc
вышеуказанным способом? Чувствуется небольшая пробка. Более того, если в будущем Abc
будет снова разделено на подклассы, оператор Equals
в Abc
необходимо обновить; это также кажется немного странным.
Есть ли рекомендуемые руководства для этого шаблона?