Вместо реализации GetHashCode
лучшим вариантом будет реализация собственного IEqualityComparer<A>
и передача его в конструктор для вашего словаря. При этом ваши правила эквивалентности не имеют смысла. Эквивалентность в программировании должна соответствовать стандартным алгебраическим правилам эквивалентности.
В вашем случае у вас есть три объекта, которые считаются "равными", что, кажется, основано на том, равно ли одно из двух свойств. Однако этот подход не предусматривает транзитивного равенства, которое необходимо. # 1 = # 2 из-за названия. # 1 = # 3 из-за кода. Однако равенство и эквивалентность требуют, чтобы, если a = b и b = c, то a = c. В вашем случае сравнение # 2 и # 3 не показывает эквивалентности или равенства, поскольку у них нет соответствующих свойств, даже если они оба равны # 1.
Короткая версия заключается в том, что ваши правила равенства / эквивалентности нельзя использовать ни с одним хранилищем на основе ключей, например Dictionary
.
Если вы убеждены, что это правильный путь, тогда это сделает то, что вы ищете, , но это не будет вести себя последовательно. Ничто не может вести себя последовательно, используя эту псевдоэквивалентность .
class AEqualityComparer : IEqualityComparer<A>
{
public bool Equals(A x, A y)
{
return x == y || x.name == y.name || x.code == y.code;
}
public int GetHashCode(A x)
{
return -1; // impossible to compute; will negatively impact performance
}
}
...
Dictionary<A, string> dict = new Dictionary<A, string>(new AEqualityComparer());
Однако это очень легко сломать:
dict[A1] = "foo";
dict[A2] = "bar";
// dict[A1] is now "bar", as expected
dict[A3] = "baz";
Здесь dict[A1]
- это "baz"
, как и ожидалось. Однако dict[A2]
равно и "baz"
, даже если A2
не равно A3
в соответствии с этими правилами. Это потому, что исходный объект был A1
, что равно обоим.