2010-11-06 4 views
7

У меня возникла проблема с GetHashCode и Equals, которые я переопределил для класса. Я использую оператор ==, чтобы убедиться, что оба они равны, и я ожидаю, что это вызовет как GetHashCode, так и Equals, если их хэш-код будет одинаковым, чтобы проверить, действительно ли они равны.C# GetHashCode/Equals override not called

Но, к моему удивлению, ни вызов, ни результат теста равенства не являются ложными (хотя это должно быть истинно).

код Override:

public class User : ActiveRecordBase<User> 

     [...] 

     public override int GetHashCode() 
     { 
      return Id; 
     } 

     public override bool Equals(object obj) 
     { 
      User user = (User)obj; 
      if (user == null) 
      { 
       return false; 
      } 

      return user.Id == Id; 
     } 
    } 

проверка равенства:

if (x == y) // x and y are both of the same User class 
    // I'd expect this test to call both GetHashCode and Equals 
+4

Если '==' и в самом деле назвать ваш 'метод Equals', то это вызовет переполнение стека, как он использует' '== оператор на объекте ... – Guffa

+0

Там нет ничего в коде вы показываете, что это указывает на необходимость вызова GetHashCode(). Это называется только, если вы используете свой объект в качестве ключа коллекции. – RenniePet

ответ

11

== Оператор полностью отделен от любого .GetHashCode() или .Equals().

Возможно, вас заинтересует Microsoft Guidelines for Overloading Equals() and Operator ==.

Краткая версия: Использовать .Equals() для реализации равенство сравнение. Используйте оператор == для идентификаторов сравнения, или если вы создаете неизменяемый тип (где каждый равный экземпляр можно считать фактически идентичным). Кроме того, .Equals() является виртуальным методом и может быть переопределен подклассами, но оператор == зависит от типа времени компиляции выражения, в котором он используется.

Наконец, чтобы быть последовательным, реализуйте .GetHashCode() в любое время, когда вы реализуете .Equals(). Оператор перегрузки != при перегрузке оператора ==.

+0

Мои объекты изменяемы. Я ожидал, что вызов оператора == на самом деле вызовет метод Equals, который я видел ранее, но я не понимаю, почему он не работает сейчас, и он работал до ... – tomzx

+0

@tomzx: The = = 'оператор никогда не вызывает метод' .Equals() ', если вы не перегрузите его для этого. –

+1

@ Daniel Ваш совет re "==" неверен. Microsoft последовательно говорит, что если вы хотите сравнить IDENTITY, вы должны использовать «ReferenceEquals». Например, рассмотрим строки. Если вы используете построитель строк, чтобы создать две строки, имеющие одинаковое СОДЕРЖАНИЕ, но разные АДРЕСЫ, тогда «==» вернет TRUE (сравнение равенства), но ReferenceEquals вернет FALSE. «==» обычно рассматривается как сравнение EQUALITY и обычно выполняется так же, как и все, что делает EQUALS класса. – ToolmakerSteve

1

возможно добавление еще одного метода в ваш класс User.

public virtual bool Equals(User other) 
    { 
     if (ReferenceEquals(null, other)) return false; 
     if (ReferenceEquals(this, other)) return true; 
     return other.Id == Id; 
    }