Question

J'ai une classe d'adresse en C # qui ressemble à ceci:

public class Address
{            
    public string StreetAddress { get; set; }
    public string RuralRoute { get; set; }
    public string City { get; set; }
    public string Province { get; set; }
    public string Country { get; set; }
    public string PostalCode { get; set; }
}

Je l'égalité et la mise en œuvre, alors je dois remplacer le code de hachage. Au début, je vais utiliser la formule de hashcode de EJ, mais je pensais: Ce sont tous les champs de chaîne, je ne peux pas tout simplement utiliser un StringBuilder pour les concaténer et retourner le code de hachage de cette chaîne

?

C'est:

var str = new StringBuilder();
str.Append(StreetAddress)
   .Append(RuralRoute)
   ...

return str.ToString().GetHashCode();

Quels sont les avantages / inconvénients de cette situation? Pourquoi ne devrais-je faire?

Était-ce utile?

La solution

J'éviter de faire cela pour la simple raison que cela crée un tas de cordes inutilement - bien que le point de Kosi2801 de faire des collisions simple est également pertinente. (Je soupçonne que ce ne serait pas en fait créer de nombreuses collisions, en raison de la nature des champs, mais ...)

Je pencherais pour l'algorithme « simple et facile à obtenir le droit » Je l'ai déjà utilisé dans cette zone réponse (merci pour regarder vers le haut lance :) - et qui est listé dans effective Java, comme vous le dites. Dans ce cas, il finirait comme:

public int GetHashCode()
{
    int hash = 17;
    // Suitable nullity checks etc, of course :)
    hash = hash * 23 + StreetAddress.GetHashCode();
    hash = hash * 23 + RuralRoute.GetHashCode();
    hash = hash * 23 + City.GetHashCode();
    hash = hash * 23 + Province.GetHashCode();
    hash = hash * 23 + Country.GetHashCode();
    hash = hash * 23 + PostalCode.GetHashCode();
    return hash;
}

Ce n'est pas nul sûr, bien sûr. Si vous utilisez C # 3, vous voudrez peut-être envisager une méthode d'extension:

public static int GetNullSafeHashCode<T>(this T value) where T : class
{
    return value == null ? 1 : value.GetHashCode();
}

Ensuite, vous pouvez utiliser:

public int GetHashCode()
{
    int hash = 17;
    // Suitable nullity checks etc, of course :)
    hash = hash * 23 + StreetAddress.GetNullSafeHashCode();
    hash = hash * 23 + RuralRoute.GetNullSafeHashCode();
    hash = hash * 23 + City.GetNullSafeHashCode();
    hash = hash * 23 + Province.GetNullSafeHashCode();
    hash = hash * 23 + Country.GetNullSafeHashCode();
    hash = hash * 23 + PostalCode.GetNullSafeHashCode();
    return hash;
}

pourrait créer un utilitaire de méthode de tableau de paramètres pour rendre ce encore plus simple:

public static int GetHashCode(params object[] values)
{
    int hash = 17;
    foreach (object value in values)
    {
        hash = hash * 23 + value.GetNullSafeHashCode();
    }
    return hash;
}

et appelez avec:

public int GetHashCode()
{
    return HashHelpers.GetHashCode(StreetAddress, RuralRoute, City,
                                   Province, Country, PostalCode);
}

Dans la plupart des types primitifs il y a impliqués, de sorte que exécuterait la boxe un peu inutilement, mais dans ce cas, il suffit avoir des références. Bien sûr, vous finiriez créer un tableau inutilement, mais vous savez ce qu'ils disent sur l'optimisation prématurée ...

Autres conseils

Ne pas le faire parce que les objets peuvent être différents barbante le hashcode est le même.

Pensez

"StreetAddress" + "RuralRoute" + "City"

vs

"Street" + "AddressRural" + "RouteCity"

Les deux auront la même hashcode mais un contenu différent dans les champs.

Pour ce genre de chose, vous voudrez peut-être mettre en œuvre IEqualityComparer<Address>:

public class Address : IEqualityComparer<Address>
{        
    //
    // member declarations
    //

    bool IEqualityComparer<Address>.Equals(Address x, Address y)
    {
        // implementation here
    }

    int IEqualityComparer<Address>.GetHashCode(Item obj)
    {
        // implementation here
    }
}

Vous pouvez également mettre en œuvre IComparable<Address> pour obtenir la commande ...

public string getfourDigitEncryptedText(string input) { 
    int hashCode = input.hashCode(); 
    string hstring = (new StringBuilder()).append(hashCode).append("").toString(); 
    string rev_hstring = (new StringBuilder(hstring)).reverse().toString(); 
    string parts[] = rev_hstring.trim().split(""); 
    int prefixint = 0; 
    for(int i = 1; i <= parts.length - 3; i++) 
        prefixint += integer.parseInt(parts[i]);   
    string prefixstr = "0"; 
    if((new integer(prefixint)).toString().length() < 2) 
        prefixstr = (new StringBuilder()).append((new integer(prefixint)).toString()).append("5").toString(); 
    else if((new integer(prefixint)).toString().length() > 2) 
        prefixstr = "79"; 
    else 
        prefixstr = (new integer(prefixint)).toString(); 
    string finalstr = (new StringBuilder()).append(prefixint).append(rev_hstring.substring(3, 5)).toString();
    return finalstr; 
}  
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top