Ответ 1
Вы правы, это много кода котельной, и вам нужно все реализовать отдельно.
Я бы порекомендовал:
- Если вы собираетесь вообще реализовать равенство значений, переопределите
GetHashCode
иEquals(object)
- создайте перегрузки для == и внедряйтеIEquatable<T>
, не делая этого, что может привести к очень неожиданному поведению - Я бы всегда реализовал
IEquatable<T>
, если вы переопределяетеEquals(object)
иGetHashCode
- Я редко перегружаю оператор ==
- Правильное выполнение равенства для незапечатанных классов является сложным и может вызвать неожиданные/нежелательные результаты. Если вам нужно равенство для типов в иерархии, выполните
IEqualityComparer<T>
, выразив интересующее вас сравнение. - Равенство для изменяемых типов обычно является плохой идеей, так как два объекта могут быть равными, а затем неравными позже... если объект мутирован (в смысле, влияющем на равенство) после того, как он использовался в качестве ключа в хеш-таблице, вы не сможете найти его снова.
- Некоторые из котельных пластин немного отличаются для структур... но, как и Марк, я очень редко пишу свои собственные структуры.
Здесь пример реализации:
using System;
public sealed class Foo : IEquatable<Foo>
{
private readonly string name;
public string Name { get { return name; } }
private readonly int value;
public int Value { get { return value; } }
public Foo(string name, int value)
{
this.name = name;
this.value = value;
}
public override bool Equals(object other)
{
return Equals(other as Foo);
}
public override int GetHashCode()
{
int hash = 17;
hash = hash * 31 + (name == null ? 0 : name.GetHashCode());
hash = hash * 31 + value;
return hash;
}
public bool Equals(Foo other)
{
if ((object) other == null)
{
return false;
}
return name == other.name && value == other.value;
}
public static bool operator ==(Foo left, Foo right)
{
return object.Equals(left, right);
}
public static bool operator !=(Foo left, Foo right)
{
return !(left == right);
}
}
И да, это чертовски много шаблонов, очень малое из которых меняется между реализациями: (
Реализация ==
немного менее эффективна, чем могла бы быть, так как она вызовет Equals(object)
, которая должна выполнить проверку динамического типа... но альтернативой является еще больше котельной пластины, например
public static bool operator ==(Foo left, Foo right)
{
if ((object) left == (object) right)
{
return true;
}
// "right" being null is covered in left.Equals(right)
if ((object) left == null)
{
return false;
}
return left.Equals(right);
}