Domanda

In sostanza, ho il seguente finora:

class Foo {
    public override bool Equals(object obj)
    {
        Foo d = obj as Foo ;
        if (d == null)
            return false;

        return this.Equals(d);
    }

    #region IEquatable<Foo> Members

    public bool Equals(Foo other)
    {
        if (this.Guid != String.Empty && this.Guid == other.Guid)
            return true;
        else if (this.Guid != String.Empty || other.Guid != String.Empty)
            return false;

        if (this.Title == other.Title &&
            this.PublishDate == other.PublishDate &&
            this.Description == other.Description)
            return true;

        return false;
    }
}

Quindi, il problema è questo: ho un campo non richiesto Guid, che è un identificatore univoco. Se questo non è impostato, quindi ho bisogno di cercare di determinare l'uguaglianza sulla base di metriche meno accurati come un tentativo di determinare se due oggetti sono uguali. Questo funziona bene, ma fanno GetHashCode() disordinato ... Come dovrei andare su di esso? Un'implementazione ingenuo sarebbe qualcosa di simile:

public override int GetHashCode() {
    if (this.Guid != String.Empty)
        return this.Guid.GetHashCode();

    int hash = 37;
    hash = hash * 23 + this.Title.GetHashCode();
    hash = hash * 23 + this.PublishDate.GetHashCode();
    hash = hash * 23 + this.Description.GetHashCode();
    return hash;
}

Ma quali sono le probabilità di due tipi di hash collisione? Certo, non mi aspetto di essere 1 in 2 ** 32. Si tratta di una cattiva idea, e se sì, come dovrei farlo?

È stato utile?

Soluzione

Non credo che ci sia un problema con l'approccio si è scelto di utilizzare. Preoccuparsi 'troppo' di eventuali collisioni hash è quasi sempre un'indicazione di un eccesso di pensare il problema; fintanto che l'hash è altamente probabile che sia diverso si dovrebbe andare bene.

In definitiva si può anche prendere in considerazione tralasciando il Description dal hash in ogni caso, se è ragionevole aspettarsi che la maggior parte degli oggetti in tempo possono essere distinti in base alla loro titolo e data di pubblicazione (libri?).

Si potrebbe anche prendere in considerazione trascurando il GUID nella funzione di hash del tutto, e solo usarlo nel Equals implementazione per disambiguare il improbabile (?) Caso di scontri di hash.

Altri suggerimenti

Un metodo codice hash molto facile per le classi personalizzate è quello di XOR bit a bit ciascuno dei codici hash campi insieme. Può essere semplice come questo:

int hash = 0;
hash ^= this.Title.GetHashCode();
hash ^= this.PublishDate.GetHashCode();
hash ^= this.Description.GetHashCode();
return hash;

sopra :

  

XOR ha le seguenti proprietà curato:

     
      
  • non dipende ordine della computazione.
  •   
  • non bit “rifiuto”. Se si cambia anche un bit in uno dei componenti, il valore finale cambierà.
  •   
  • E 'veloce, un singolo ciclo avanti anche il computer più primitivo.
  •   
  • Conserva distribuzione uniforme. Se i due pezzi che si uniscono sono uniformemente distribuite in modo sarà la combinazione essere. In altre parole, non tende a comprimere la gamma del digest in una banda più stretta.
  •   

XOR non funziona bene se si aspetta di avere valori duplicati nei campi come valori duplicati si annullano a vicenda, quando XORed. Dal momento che stai hashing insieme tre campi non collegati che non dovrebbe essere un problema in questo caso.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top