sobota, 15 marca 2014

Equals powinno służyć nam do porównywania obiektów pod względem zawartości. Istnieją sytuacje gdzie mimo, że wskaźniki pokazują na całkiem dwa różne obiekty, w naszym rozumieniu, obiekty te mogą być sobie równe. Na przykład to czy obiekty typu Account, są sobie równe, zależy od tego jakie posiadają ID, niezależnie od tego czy referencja jest do tej samej, czy do innej instancji obiektu.

Domyśla implementacja, zawarta w klasie obiect sprawdza czy wskaźniki pokazują na to samo miejsce w pamięci. Jeśli chcemy napisać własną wersję metody Equals należy przedefiniować (override). Poniżej przykładowa implementacja dla klasy Account:

public override bool Equals(object a_obj)
{
    if (ReferenceEquals(null, a_obj)) 
        return false;
            
    if (ReferenceEquals(this, a_obj)) 
        return true;
            
    if (a_obj.GetType() != this.GetType()) 
        return false;
            
    return Equals((Account) a_obj);
}

protected bool Equals(Account a_other)
{
    return m_id == a_other.m_id;
}

public override int GetHashCode()
{
    return m_id;
}

Zalecane/wymagane jest aby metoda GetHashCode obliczała hashcode na tych samych składnikach co wykonuje się porównanie w metodzie Equals. Porównanie hashcodów jest szybsze od porównywania wszystkich składników obiektu i w związku z tym jest często wykorzystywane w słownikach.

Operator porównania '==" nie wykorzystuje w tle metody Equals. Operator ten porównuje wskaźniki. Można to łatwo zmienić:

public static bool operator ==(Account a_left, Account a_right)
{
    return Equals(a_left, a_right);
}

public static bool operator !=(Account a_left, Account a_right)
{
    return !Equals(a_left, a_right);
}

Należy pamięć, że operatory nie są wirtualne i tutaj dochodzi do przeładowania (overload) a nie do przedefiniowania. Kompilator będzie próbował dopracować wywołanie do najbardziej pasującej, dostępnej wersji metody operatora. Jeśli podziedziedziczymy po klasie Account, i wykonamy porównanie na dwóch instancja obiektów typu pochodnego to kompilator dopasuje wywołanie do operatora zdefiniowanego w klasie podstawowej.

Categories:

0 komentarze :

Prześlij komentarz