2010-11-21 19 views
28

Jak wiesz, GetHashCode zwraca wartość semi-unique, która może być użyta do identyfikacji instancji obiektu w kolekcji. Jako dobrą praktykę zaleca się zastąpienie tej metody i wdrożenie własnej.Nadpisywanie kodu GetHashCode

Moje pytanie brzmi - czy zastępujesz tę metodę podczas pracy nad niestandardowymi obiektami? Jeśli tak, to jakiego algorytmu używasz do generowania unikalnego identyfikatora?

Zastanawiam się nad wygenerowaniem identyfikatora GUID, a następnie uzyskaniem danych liczb całkowitych z tego identyfikatora.

+2

Mają lektury [to pytanie] (http: // stackoverflow.com/questions/263400/what-is-is-the-best-algorithm-for-anridden-system-object-gethashcode) i jego odpowiedzi. Przedstawia on dobrą implementację kodu skrótu. Istnieje również dobra dyskusja na temat ominięcia 'GetHashCode' dla zmiennych obiektów [tutaj] (http://stackoverflow.com/questions/873654/overriding-gethashcode-for-muteable-objects-c). – adrianbanks

+7

Nie wiem, co "pół-unikalny" oznacza ... wartość jest albo unikalna, albo nie jest, a kod skrótu nie jest unikalny. Dlatego nie pozwala na identyfikację obiektu na liście. I nie jest to "dobrą praktyką" nadpisywanie 'GetHashCode', to jest coś, co robisz, kiedy * potrzebujesz *, aby (np. Użyć obiektu jako klucza w słowniku), a nie dlatego, że uważasz, że jest to dobra praktyka. –

+0

Używanie obiektu jako klucza można uznać za identyfikujące obiekt w kolekcji - właśnie dlatego szukam informacji na temat najlepszego algorytmu do budowania identyfikatora. Od pół-unikalnych identyfikatorów: http://www.west-wind.com/Weblog/posts/4741.aspx –

Odpowiedz

24

Po nadpisaniu GetHashCode() należy również zastąpić Equals(), operator== i operator!=. I bądź bardzo ostrożny, aby spełnić wszystkie wymagania dla tych metod.

Wytycznymi są here on MSDN. Najważniejszy cytat:

Nie należy przesłonić operatora == w niezmiennym typie.

+0

Z tego co rozumiem, to nie ma sensu, ponieważ, cóż, obiekt nie zmieni tego stanu . –

+0

Co nie ma sensu? –

+0

Przesłanianie operatora ==. –

-2

Generalnie używam zagregowanej klasy GetHashCode z właściwości komponentu klasy. Na przykład.

public class Test 
{ 
    public string Text { get; set; } 
    public int Age { get; set; } 

    public override GetHashCode() 
    { 
    int result = 
     string.IsNullOrEmpty(Text) ? 0 : Text.GetHashCode() 
     + Age.GetHashCode(); 

    return result; 
    } 
} 
+5

To nie jest najlepszy sposób, aby to zrobić, zobacz http://stackoverflow.com/questions/263400/what-is-the-best-algorithm-for-an-overridden-system-object-gethashcode –

+0

Ogólnie rzecz biorąc nie jest dobre do tworzenia złożonego kodu szyfrującego. Ale w tym konkretnym przykładzie nie widzę z tym problemu. Ale oczywiście nadrzędny GetHashCode bez przesłonięcia równań nie ma większego sensu. – CodesInChaos

+0

Cóż, uczysz się czegoś każdego dnia! –

1

W moim osobistym użyciu, tylko przesłonię, gdy nadpisuję metodę równą. Zasadniczo robię to dla obiektów, które wiem, że mogę uruchomić kwerendę LINQ to Objects lub inną operację porównania.

Zazwyczaj zwracam, jeśli na przykład obiekt LINQ do obiektu SQL lub obiektu DTO, wartość klucza podstawowego. Cokolwiek zwrócisz, jeśli nie przechowujesz wartości lokalnie, może to spowodować nieoczekiwany wynik.

HTH.

0

wystarczy zastąpić GetHashCode, jeśli zastępujesz Equals. Domyślny kod GetHashCode jest implementowany przez środowisko wykonawcze w podobny sposób, w jaki chciałeś to zrobić - każdy obiekt ma ukryte pole przypisane przez środowisko wykonawcze.

How to override GetHashCode

Właściwie IDE powinien to zrobić dla Ciebie - po wpisaniu „przesłonić GetHashCode” IDE powinien generować kod szablonowe. Visual Studio nie robi tego, ale robi to tylko SharpDevelop.

+0

Domyślna implementacja metody GetHashCode nie gwarantuje unikalnych wartości zwracanych dla różnych obiektów. W związku z tym domyślna implementacja tej metody nie może być używana jako unikalny identyfikator obiektu dla celów mieszania. Od: http://msdn.microsoft.com/en-us/library/system.object.gethashcode.aspx – brain

+0

w VS trzeba użyć fragmentu 'równy' zamiast tego – CodesInChaos

+1

@brain - czytam to. Czy to oznacza, że ​​zawsze należy przesłonić GetHashCode, gdy chcesz przechowywać swoje obiekty w słowniku? Nie sądzę - prawie nikt tego nie robi. Domyślna implementacja działa dobrze na potrzeby słownika. To nie jest idealne, ale w porządku: http://stackoverflow.com/questions/750947/net-unique-object-identifier –

1

Normalnie zastąpiłbym metody sprawdzania kodu kreskowego i równości dla klas danych (tj. Klas, w których sensowna jest semantyka wartości). Zajrzyj do pytania this dla wspólnej implementacji. Jeśli przesłonisz nadpisanie kodu hashowego, to znaczy. Używanie identyfikatora GUID jest dość przerażającym pomysłem, ponieważ potrzebujesz dwóch obiektów, które są różnymi instancjami, ale mają taką samą wartość wartości, aby mieć ten sam kod skrótu, a dla równości zwracają wartość true.

27

Jeśli użyjesz funkcji resharper, może wygenerować dla Ciebie ciała metody GetHashCode(), Equals i operatora.

Dostęp do tego menu przez naciśnięcie klawisza Alt + Wstaw.

http://www.jetbrains.com/resharper/webhelp/Code_Generation__Equality_Members.html

+1

http://www.jetbrains.com/resharper/webhelp/Code_Generation__Equality_Members.html – Deinonychus

+2

Łatwiejszy sposób, który nie wstawia tylu zestawów znaków i pozostaje aktualny po zmianie klasy: http: //eamonnerbonne.github .io/ValueUtils/ –

+0

Z jakiegokolwiek powodu alt + insert nie otwiera mojego menu resharper, ale mogę użyć menu: Resharper -> Edit -> Generate Code ... –