2016-05-09 19 views
10

breve domandaHashing un array in C#

Come implementare GetHashCode per un Array.

dettagli

Ho un oggetto che sostituisce Equals, controllando che:

this.array[n] == otherObject.array[n] 

per tutti n in array.

Naturalmente dovrei implementare il complementare GetHashCode. Mi chiedevo se c'è NET modo per fare questo, o se devo realizzare il mio, qualcosa come

hash = hash^array[n] 

Chiarimento

mio oggetto contiene un array, e sono interessati a GetHashCode per gli elementi dell'array. Il mio codice per l'equivalenza degli array è solo per esempio - come dice la mia domanda ma forse non ero chiaro, sono interessato a GetHashCode (non Equals). Dico che naturalmente dovrei implementare il complementare GetHashCode perché è un requisito di .NET implementarlo una volta che Equals viene sovrascritto (per Dictionary ecc. Per funzionare correttamente). Grazie.

+0

Dai un'occhiata alla risposta pubblicata [qui] (http://stackoverflow.com/a/7244729/833070). In altre parole, è meglio implementare la propria variazione o utilizzare un altro strumento, non è possibile utilizzare 'GetHashCode()' o 'Equals()' per una matrice – Draken

+0

Perché non fare 'this.array [n]. Uguale (otherObject.array [n]) 'per' n'? –

+1

Se si desidera confrontare due array per l'uguaglianza, è possibile utilizzare l'estensione 'SequenceEqual' –

risposta

4

Per calcolare un codice hash utilizzando gli elementi di un array, si può lanciare l'array IStructuralEquatable e quindi chiamare il metodo GetHashCode(IEqualityComparer), passando un operatore di confronto per il tipo di elementi in l'array.

(Il cast è necessario perché la classe Array implementa esplicitamente il metodo.)

Ad esempio, se l'oggetto dispone di una serie int, allora è possibile implementare GetHashCode in questo modo:

public override int GetHashCode() 
{ 
    return ((IStructuralEquatable)this.array).GetHashCode(EqualityComparer<int>.Default); 
} 

Nel caso foste curiosi, ecco come la classe Array implementa il metodo GetHashCode (dal Reference Source):

internal static int CombineHashCodes(int h1, int h2) { 
    return (((h1 << 5) + h1)^h2); 
} 

int IStructuralEquatable.GetHashCode(IEqualityComparer comparer) { 
    if (comparer == null) 
     throw new ArgumentNullException("comparer"); 
    Contract.EndContractBlock(); 

    int ret = 0; 

    for (int i = (this.Length >= 8 ? this.Length - 8 : 0); i < this.Length; i++) { 
     ret = CombineHashCodes(ret, comparer.GetHashCode(GetValue(i))); 
    } 

    return ret; 
} 

Come si può vedere, l'implementazione corrente utilizza solo gli ultimi otto elementi della matrice.

2

non sono d'accordo, naturalmente, si dovrebbe implementare GetHashCode su un array
Si dovrà aggiornarlo con ogni cambio
o calcolare al volo
Vorrei confrontare direttamente al volo
SequenceEquals useranno il confronto uguaglianze predefinito così si dovrebbe anche implementare

public bool Equals 

0n gli oggetti nel matrice

0.123.

Enumerable.SequenceEqual
ha un esempio

public static void SequenceEqualEx1() 
{ 
    Pet pet1 = new Pet { Name = "Turbo", Age = 2 }; 
    Pet pet2 = new Pet { Name = "Peanut", Age = 8 }; 

    // Create two lists of pets. 
    List<Pet> pets1 = new List<Pet> { pet1, pet2 }; 
    List<Pet> pets2 = new List<Pet> { pet1, pet2 }; 

    bool equal = pets1.SequenceEqual(pets2); 

    Console.WriteLine(
     "The lists {0} equal.", 
     equal ? "are" : "are not"); 
} 
+2

L'OP ha implementato uguale su un oggetto che * contiene * un array. È naturale implementare anche GetHashCode su quell'oggetto. –

+0

@ MichaelLiu Non come l'ho letto. Non sto leggendo un oggetto che * contiene * un array. L'ho letto come oggetti * in * l'array override equals this.array [n] == otherObject.array [n]. – Paparazzi

+1

Perché un oggetto * in * l'array ha un metodo Equals che fa riferimento a 'this.array'? Ciò significa che hai una serie di oggetti che a loro volta contengono array. –