2012-01-27 11 views

risposta

17

non vedo il motivo per cui avresti bisogno di uno. Se si desidera creare un hash-codice basato sul default GetHashCode di 3 articoli diversi, poi basta usare:

Tuple.Create(lastName, firstName, gender).GetHashCode() 

Questo ti riducono a l'equivalente di:

int h1 = lastName.GetHashCode(); 
int h2 = firstName.GetHashCode(); 
int h3 = gender.GetHashCode(); 
return (((h1 << 5) + h1)^(((h2 << 5) + h2)^h3)); 

che è abbastanza ragionevole per tale combinazione generica.

Allo stesso modo:

Tuple.Create(lastName, firstName, gender).Equals(Tuple.Create(lastName2, firstName2, gender2)) 

si ridurrebbe all'equivalente di chiamare:

return ((lastName == null && lastName2 == null) || (lastName != null && lastName.Equals(lastName2))) 
    && ((firstName == null && firstName2 == null) || (firstName != null && firstName.Equals(lastName2))) 
    && ((gender == null && gender2 == null) || (gender != null && gender.Equals(lastName2))); 

Anche in questo caso, circa buono come ci si potrebbe aspettare.

+1

+1: tuple e tipi anonimi sono ottimi per implementare GetHashCode(), Equals() e ToString() – millimoose

+1

Bella idea che usa le classi 'Tuple' come scorciatoia. Ma nota che 'Tuple.Create (...). Equals (Tuple.Create (...))' non è equivalente al metodo 'equals' di Guava - sarebbe semplicemente' object.Equals (x, y) '. – LukeH

+1

@LukeH, beh visto che ce l'abbiamo già, e anche questo ce l'abbiamo, il che significa che possiamo fare meglio di Guava :) –

1

AFAIK nessuno. Tuttavia, scrivere il proprio non dovrebbe essere troppo complesso (nb utilizzando una variante del hash Bernstein):

public static class Objects 
{ 
    public static bool Equals<T>(T item1, T item2, Func<T, IEnumerable<object>> selector) 
    { 
    if (object.ReferenceEquals(item1, item2) return true; 
    if (item1 == null || item2 == null) return false; 

    using (var iterator1 = selector(item1).GetEnumerator()) 
    using (var iterator2 = selector(item2).GetEnumerator()) 
    { 
     var moved1 = iterator1.MoveNext(); 
     var moved2 = iterator2.MoveNext(); 
     if (moved1 != moved2) return false; 
     if (moved1 && moved2) 
     { 
     if (!Equals(iterator1.Current, iterator2.Current)) return false; 
     } 
    } 
    return true; 
    } 

    public static bool Equals(object item1, object item2) 
    { 
    return object.Equals(item1, item2); 
    } 

    public static int GetHashCode(params object[] objects) 
    { 
    unchecked 
    { 
     int hash = 17; 
     foreach (var item in objects) 
     { 
     hash = hash * 31 + item.GetHashCode(); 
     } 
     return hash; 
    } 
    } 
} 
+0

Il metodo 'Equals' è esattamente uguale al metodo statico incorporato' object.Equals (x, y) ': http://msdn.microsoft.com/en-us/library/w4hkze5k.aspx – LukeH

+0

@ Lucah Grazie - perché reinventare la ruota ?! Risposta aggiornata –

+0

'Equals' non è più utile dell'implementazione standard ereditata. Deve essere possibile stabilire quali campi dovrebbero essere considerati per l'uguaglianza. – deamon