2010-07-23 17 views
13

Hej wszystkim, czytałem o najlepszym sposobie implementacji nadpisania GetHashCode() dla obiektów w .NET, a większość odpowiedzi, na które napotykam, polega w jakiś sposób na zgniataniu liczb od członków, którzy są typy liczbowe do wymyślenia metody. Problem polega na tym, że mam obiekt, który używa klucza alfanumerycznego jako klucza i zastanawiam się, czy jest coś zasadniczo nie tak z użyciem wewnętrznego identyfikatora obiektów z łańcuchami jako kluczami, coś jak poniżej?GetHashCode() z kluczami ciągów znaków


// Override GetHashCode() to return a permanent, unique identifier for 
// this object. 
static private int m_next_hash_id = 1; 
private int m_hash_code = 0; 
public override int GetHashCode() { 
    if (this.m_hash_code == 0) 
    this.m_hash_code = <type>.m_next_hash_id++; 
    return this.m_hash_code; 
} 

Czy istnieje lepszy sposób wymyślenia unikatowego kodu skrótu dla obiektu, który używa ciągu alfanumerycznego jako klucza? (I nie, części numeryczne ciągu alfanumerycznego nie są unikalne, niektóre z tych ciągów w ogóle nie zawierają liczb.) Wszelkie przemyślenia zostaną docenione!

Odpowiedz

19

Można zadzwonić pod numer GetHashCode() na wartości nieliczbowe, które są używane w obiekcie.

private string m_foo; 
public override int GetHashCode() 
{ 
    return m_foo.GetHashCode(); 
} 
+0

Ale co jeśli ten ciąg się zmieni? Na przykład mogę utworzyć nowy obiekt użytkownika za pomocą: User foo = new User(); a konstruktor ustawia User.Id = "". Później, jeśli powiem, User.Id = "A12345"; i zwrócę this.Id.GetHashCode() jako wynik foo.GetHashCode(), czy to się nie zmieniło, naruszając zasadę, że kod mieszający obiektu nigdy nie powinien się zmieniać? –

+6

Obiekt zmieniony. Kod skrótu * również musi się zmienić *. –

+0

@King - istnieje kilka różnych sposobów korzystania z kodów skrótów. Wartość kodu skrótu musi być zawsze taka sama, z tą samą wartością początkową. Jeśli twoja wartość jest zmienna, musisz zapisać wynikowy kod skrótu i ​​zwrócić go, gdy zostanie wywołana metoda 'GetHashCode()'. –

0

Tak, lepszym sposobem byłoby użycie hashcode ciągu, który już masz. Jeśli ciąg znaków alfanumerycznych definiuje tożsamość obiektu, który posiadasz, jego kodowanie będzie całkiem przyjemne dla kodu skrótu twojego obiektu.

Idea zwiększania pola statycznego i używania go jako kodu haszującego jest zła. Kod mieszania powinien mieć równomierną dystrybucję na przestrzeni możliwych wartości. Zapewnia to, między innymi, że będzie działał dobrze, gdy zostanie użyty jako klucz w hashtable.

0

Wierzę, że na ogół chcą GetHashCode() powrócić coś, co identyfikuje obiekt, to jest wartość, a nie jest to przypadek, czy jestem zrozumienia idei tutaj, myślę, że metoda zapewniłaby GetHashCode() na dwóch różnych obiektów o równoważnych wartościach będzie zwracaj różne skróty tylko dlatego, że są różnymi instancjami.

GetHashCode() służy do zwracania wartości, która umożliwia porównywanie wartości dwóch obiektów, a nie ich odniesień.

2

Kody kreskowe nie muszą być unikatowe. Pod warunkiem, że implementacja Equals jest poprawna, możesz zwrócić ten sam kod skrótu dla dwóch wystąpień. Logika m_next_hash_id jest zepsuta, ponieważ pozwala dwóm obiektom mieć różne kody skrótu, nawet jeśli porównują one.

MSDN udostępnia zestaw instrukcji dotyczących wdrażania Equals i GetHashCode. Several of the examples here implement GetHashCode implementacja kodu skrótu pól obiektu

18

To nie jest dobry wzorzec do generowania skrótów dla obiektu.

Ważne jest undunderstand cel GetHashCode() - jest sposób generowania numeryczną reprezentację właściwości identyfikacji obiektu. Hasła są używane, aby obiekt mógł służyć jako klucz w słowniku, a w niektórych przypadkach przyspieszyć porównywanie typów złożonych.

Jeśli po prostu wygenerujesz losową wartość i nazwiesz ją kodem mieszania, nie będziesz miał powtarzalności. Inna instancja z tymi samymi kluczowymi polami będzie miała inny kod skrótu i ​​będzie naruszać zachowanie oczekiwane przez klasy takie jak HashSet, Dictionary, itp.

Jeśli posiadasz już identyfikujący element ciągu w swoim obiekcie, po prostu zwróć jego kod skrótu .

documentation on MSDN for implementers of GetHashCode() to lektura obowiązkowa dla każdego, kto planuje na nadrzędnych tej metody:

notatek do realizatorów

funkcji mieszającej służy do szybkiego generowania numeru (hash kod), który odpowiada wartości obiektu o wartości . Funkcje skrótu są zwykle specyficzne dla każdego typu, a dla unikalności muszą używać co najmniej jednego z pól instancji jako danych wejściowych.

Funkcja skrótu może mieć następujące właściwości:

Jeśli dwa obiekty porównanie jako równe, przy czym sposób GetHashCode dla każdego obiektu muszą powrócić tą samą wartość. Jednak jeśli dwa obiekty nie są takie same, jak dwa różne obiekty, nie można porównywać jako , to nie trzeba zwracać różnych wartości w postaci .

Metoda GetHashCode dla obiektu musi stale ten sam kod powrotu hash tak długo jak nie ma zmiany stanu obiektu, który określa wartość powrotna obiektu równa metody. Zauważ, że ta jest prawdziwa tylko dla bieżącego wykonania aplikacji aplikacji i że inny kod skrótu może zostać zwrócony, jeśli aplikacja zostanie uruchomiona ponownie.

Aby uzyskać najlepszą wydajność, funkcja mieszania musi generować losowy rozkład dla wszystkich danych wejściowych.

Na przykład, wdrożenie metody GetHashCode dostarczonych przez klasę String zwraca identyczny hash kodów dla identycznych wartości ciągów. Dlatego dwa obiekty String zwracają kod z tym samym kodem mieszającym, jeśli reprezentują one tę samą wartość ciągu. Również metoda wykorzystuje wszystkie znaki w ciągu wygenerować dość losowo rozproszoną produkcję, nawet gdy wejście jest skupione w pewnych zakresach (na przykład, wielu użytkowników może mieć ciągi, które zawierają tylko dolną 128 ASCII znaków, nawet jeśli ciąg znaków może zawierać dowolny ze znaków Unicode o długości 65,535 ).

Powiązane problemy