Преимущество извлечения внешнего класса из IEqualityComparer <> перед переопределением GetHashCode и Equals - PullRequest
5 голосов
/ 22 февраля 2012

Мне нужно хешировать переменную-член вместо класса, поэтому я не проверяю, есть ли ссылка в словаре.Без переопределения значений по умолчанию он не найдет идентичный Value, а вернет его, только если найдет тот же точный экземпляр HashedType, такой, что этот код завершится ошибкой.

Dictionary.Add(new HashedType(4));
Dictionary.Contains(new HashedType(4)); // fails to find 4

Определение HashedType:

HashedType
{
   public HashedType(Int32 value) { Value = value); }
   public HashedType(String value) { Value = value); }
   public object Value;
   public void Serialize(Serializer s)
   {
      if (Value.GetType() == typeof(Int32)) 
      {
         s.Set<Int32>(0);
         s.Set<Int32>(Value);
      }
      else 
      {
         s.Set<Int32>(1);
         s.Set<String>(Value);
      }

   }
}

Похоже, я могу переопределить GetHashCode () и Equals (), чтобы сделать это для меня.

Однако MSDN рекомендует создать отдельный класс, который я наследую от IEqualityComparer, и создать его экземплярмои словари использовали HashedType с HashedTypeComparer: IEqualityComparer.

Чтобы упростить это, я извлек из словаря и создал

HashedTypeDictionary<U> : Dictionary<T,U> 
{ 
   public HashedTypeDictionary() : base(new  HashedTypeComparer()) { } 
   public bool Equals(HashedType a, HashedType b) { return a.Value == b.Value; }
   publci int GetHashCode(HashedType a) { return a.Value.GetHashCode(); } 
}

Это все кажется надуманным.

Разве единственное преимущество, которое я получаю, это не изменять Equals ()?

Я имею в виду, на самом деле, я бы хотел, чтобы Equals сравнивался с этим единственным членом в любом случае.

Ответы [ 4 ]

4 голосов
/ 22 февраля 2012

Идея состоит в том, что object.Equals является естественным равенством для этого типа (и GetHashCode должно соответствовать этой идее равенства).IEqualityComparer используется, когда требуется разное равенство в каждом конкретном случае.

Рассмотрим, например, string.Переопределенные методы Equals & GetHashCode выполняют сравнения с учетом регистра.Но что, если вам нужен словарь, в котором ключи не чувствительны к регистру?Вы пишете IEqualityComparer без учета регистра и передаете его в конструктор словаря.

Ваши примеры звучат так, как будто любые два экземпляра HashedType обычно рассматриваются как равные, если их членыравны.В этом случае я бы рекомендовал переопределить методы object.Equals и object.GetHashCode и не писать IEqualityComparer.

3 голосов
/ 22 февраля 2012

Причина, по которой вы выбрали бы один из других, заключается в том, хотите ли вы всегда , чтобы экземпляры данного типа сравнивались с использованием определенной логики, или только в этой одной ситуации.1005 * и GetHashCode обеспечивают "истинную" реализацию , если два объекта логически равны .IEqualityComparer позволяет вам переопределить это в на индивидуальной основе и разделить владение (это могут быть разные стороны, которые контролируют сущности, а не код, использующий их).

2 голосов
/ 22 февраля 2012

Представьте себе на мгновение, что вы не не владеете базовым классом (т.е. он создан другой командой или передан вам только в виде двоичного файла). Вы всегда можете создать IEqualityComparer. Возможно, у вас нет возможности изменить Equals и GetHashCode ...

0 голосов
/ 22 февраля 2012

Если в большинстве случаев вы хотите, чтобы поведение словаря работало по умолчанию, переопределяйте GetHashCode и Equals.Помните, что для того, чтобы это работало, они никогда не должны изменяться в течение жизненного цикла объекта - поэтому, если они запускают значение Value, значение Value должно быть установлено в конструкторе, а свойство доступно только для чтения.

IEqualityComparer действительно используетсякогда вы хотите сравнить вещи по-разному в одном разделе вашей программы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...