2008-09-16 6 views
6

Реализация Equals() для ссылочных типов сложнее, чем кажется. Мой нынешний канонический реализация выглядит следующим образом:Что такое «лучшая» каноническая реализация Equals() для ссылочных типов?

public bool Equals(MyClass obj) 
{ 
    // If both refer to the same reference they are equal. 
    if(ReferenceEquals(obj, this)) 
    return true; 

    // If the other object is null they are not equal because in C# this cannot be null. 
    if(ReferenceEquals(obj, null)) 
    return false; 

    // Compare data to evaluate equality  
    return _data.Equals(obj._data); 
} 

public override bool Equals(object obj) 
{ 
    // If both refer to the same reference they are equal. 
    if(ReferenceEquals(obj, this)) 
    return true; 

    // If the other object is null or is of a different types the objects are not equal. 
    if(ReferenceEquals(obj, null) || obj.GetType() != GetType()) 
    return false; 

    // Use type-safe equality comparison 
    return Equals((MyClass)obj); 
} 

public override int GetHashCode() 
{ 
    // Use data's hash code as our hashcode 
    return _data.GetHashCode(); 
} 

Я думаю, что это охватывает весь угол (наследование и такие) дела, но я могу ошибаться. Ребята, что вы думаете?

ответ

4

Я написал довольно подробное руководство по этому вопросу назад. Для начала ваши равные реализации должны быть разделены (т. Е. Перегрузка, принимающая объект, должна проходить до той, которая берет строго типизированный объект). Кроме того, вам необходимо учитывать такие вещи, как ваш объект, который должен быть неизменным из-за необходимости переопределять GetHashCode. Более подробная информация здесь:

http://gregbeech.com/blog/implementing-object-equality-in-dotnet

0

Это зависит от того, записываете ли вы тип значения или ссылочный тип. Для сортируемого типа значения я рекомендую это: A code snippet for Visual Studio 2005 that implements a skeleton value type adhering to Framework Design Guidelines

+0

Я знаю, что реализация для типов значений отличаются. Я спрашивал о ссылочных типах. – 2008-09-16 19:04:22

+0

Сломанная ссылка. : | – Restuta 2012-02-15 07:53:34

+0

Я исправил неработающую ссылку ... – 2012-02-22 22:39:52

0

Что касается наследования, я думаю, вы должны просто позволить парадигме ОО делать свою магию.

В частности, необходимо удалить проверку GetType(), это может привести к поломке полиморфизма по линии.

0

Я согласен с chakrit, объекты разных типов должны быть семантически равными, если они имеют одинаковые данные или ID.

Лично я использую следующие:

public override bool Equals(object obj) 
    { 
     var other = obj as MyClass; 
     if (other == null) return false; 

     return this.data.Equals(other.data); 
    } 
1

Лучше надеяться, что this._data не равно нулю, если это также тип ссылки.

public bool Equals(MyClass obj) 
{ 
    if (obj == null) { 
     return false; 
    } 
    else { 
     return (this._data != null && this._data.Equals(obj._data)) 
         || obj._data == null; 
    } 
} 

public override bool Equals(object obj) 
{ 
    if (obj == null || !(obj is MyClass)) { 
     return false; 
    } 
    else { 
     return this.Equals((MyClass)obj); 
    } 
} 

public override int GetHashCode() { 
    return this._data == null ? 0 : this._data.GetHashCode(); 
}