2010-10-12 12 views
5

Zastanawiam się nad tym, więc sądzę, że o to zapytam.GetHashCode Equality

Większość miejsc będzie można zobaczyć użyć tej samej logiki dla semantycznej nadrzędnym jest równa jak GetHashCode równości memberwise ... Jednak zazwyczaj stosują różne implementacje:

public override bool Equals(object obj) 
    { 
     if (obj == null || GetType() != obj.GetType()) 
     { 
      return false; 
     } 
     var other = (MyType)obj; 
     if (other.Prop1 != Prop1) 
     { 
      return false; 
     } 
     return true; 
    } 

    public override int GetHashCode() 
    { 
     int hash = -657803396; 
     num ^= Prop1.GetHashCode(); 
     return num; 
    } 

Jeśli realizacji równości memberwise dla danego typu (powiedzmy do przechowywania w słowniku), to dlaczego nie po prostu zastąpić GetHashCode następnie zrobić coś takiego dla wynosi:

public override bool Equals(object obj) 
    { 
     return this.HashEqualsAndIsSameType(obj); 
    } 

    public static bool HashEquals(this object source, object obj) 
    { 
     if (source != null && obj != null) 
     { 
      return source.GetHashCode() == obj.GetHashCode(); 
     } 
     if (source != null || obj != null) 
     { 
      return false; 
     } 
     return true; 
    } 

    public static bool HashEqualsAndIsSameType<T>(this T source, object obj) 
    { 
     return (obj == null || obj.GetType() == typeof(T)) && source.HashEquals(obj); 
    } 

Odpowiedz

10

Ponieważ istnieje jest realne ryzyko konfliktów. Hash-kody są niepowtarzalne nie. Mogą (gdy są różne) dowodzić nierówności, ale nigdy nie mają równości. Gdy szukasz elementu:

  • uzyskać hash kod (y)
  • jeśli hash kodu jest inny, przedmiot jest inny; wyrzucić go
  • jeśli hash kodu jest taka sama, check wynosi:
  • jeśli Równa raporty true są takie same
  • jeszcze wyrzucić

Rozważmy long ... od hash-Code jest int łatwo zauważyć, że istnieje wiele konfliktów.

+0

W jaki sposób poleciłbyś wdrożenie członka GetHashCode/Equals z najmniejszą ilością powielonych referencji członków? Takie duplikacje mogą prowadzić do przypadkowych ominięć i powodować poważne problemy (co dzisiaj wywołało moje pytanie). Co się stanie, jeśli potrzebujemy unikalnej sumy kontrolnej dla obiektu. Czy istnieje już dobry interfejs do definiowania, że ​​typ oferuje możliwość obliczania sumy kontrolnej? – Jeff

+0

@jeff to bardzo rzadkie, czego potrzebujesz, ale narzędzia takie jak resharper zrobią to za ciebie –

+0

Jeden przykład - optymistyczne buforowanie w trybie offline i/lub blokowanie obiektów różnych typów (innymi słowy, nie ma kolumny na stole w baza danych do oznaczenia identyfikatorem wersji). Klient i serwer potrzebują sposobu obliczania sumy kontrolnej lub sumy kontrolnej (którą nazwałbyś to), która jest unikalna, tak więc jeśli klient odeśle z powrotem nieaktualną wersję do serwera, serwer wie, że nie należy jej zapisywać i wyrzucać wyjątek. W jaki sposób oblicza się sumę kontrolną/sumę kontrolną w tym celu? – Jeff

1

Hashe nie są 1-do-1, można mieć wiele różnych wartości hash do tego samego wartość, ale która powinna com pare jako nie równe. Tak naprawdę nie można zaimplementować Equals pod względem GetHashCode. Właśnie dlatego masz kolizje w tabeli mieszającej i dlaczego wyszukiwanie tablicy mieszającej musi obejmować wywołanie (wywołania) zarówno do GetHashCode, jak i do Equals.

Powiązane problemy