un filo di teoria per chiarire la questione: il metodo GetHashCode() serve per generare dei riferimenti interi per classi non standard.
Lo scopo di tale procedura è unicamente uno: permettere alla classe che uno sta creando, qualora servisse, di poter gestire una chiamata al metodo Equals() in maniera efficiente.
Questo viene particolarmente utile quando la classe viene usata come chiave di una mappa (Dizionario, tabella di Hash o grafo che sia), in quando all'inserimento di un nuovo KeyValuePair all'interno della struttura dati, il compilatore chiama Equals su ogni elemento per capire dove inseire la struttura richiesta. Se la classe è un'intero o una stringa la cosa è semplice,il metodo GetHashCode() richiama direttamente il numero o la reppresentazione intera di tale numero, ma se la struttura è Custom allora ci deve pensare il programmtore a generare qualcosa si sensato.
L'obiettivo finale è sempre lo tesso: pensare a tutti i posssibili valori che la classe potrà contenere (campo per campo), identificare un range e spalmare uniformemente questo range immaginario sul campo intero (o meglio sul campo Int32), in modo che nell'uso generico standard, i numeri di hash che vengono generati siano molto diversi tra di loro e uniformemente densi in Int32.
Questo permette una maggior efficienza durante i processi di ordinamento e ricerca su strutture dati complesse (non le liste o le SortedLists o gli array, che sono invece ordinati per posizione) e accoppiate (chiave/Valore).
NOTA: Il metodo Equals() chiama sempre GetHashCode().
NOTA 2: il CLR restituisce sempre warning se una classe sovraccarica l'interfaccia IComparable o sovraccarica gli operatori == e !=. Vuole un GetHashCode() sensato per quella classe, non perchè serva, ma perchè tale classe può essere una chiave per una struttura ordinata e GetHashCode() a tal punto viene chiamato ad ogni interazione con la struttura stessa.
In ultimo, GetHasCode per le strutture valore deriva sempre dai tipo valore che contiene. Per i tipi riferimento (le classi in generale, tale metodo è basato sulla chiamata di object.GetHashCode(), il che non fa altro che scalare sul campo Int32 l'indirizzo fisico nell'heap; questo porta a dire che due classi uguali non avranno mai lo stesso valore di hash visto il fatto che non risiedono mai sulla stessa posizione di memoria, pur contenendo tutte e due gli stessi valori (campo per campo). Per assurdo, una classe
class A{
public class1 field1;
public class2 field2;
public class3 field3;
public A()
{
field1= new class1();
field2 = new class2();
field3 = new class3();
}
}
e due istanze definite come
A istanza1 = new A();
A istanza2 = new A();
istanza2.field1 = istanza1.field1;
istanza2.field2 = istanza1.field2;
istanza2.field3 = istanza1.field3;
Risulterà sempre che istanza1.GetHashCode() risulta diverso da istanza2.GetHashCode() (il che è concettualmente sbagliato anche per scopi comuni senza dizionari o mappe).
Alessandro Parma
Programmazione multipla scoposta con prognosi ancora da definirsi