Question

Est-ce la meilleure façon de créer un comparateur pour l'égalité de deux dictionnaires? Cela doit être exact. Notez que Entity.Columns est un dictionnaire de KeyValuepair (String, Object):

public class EntityColumnCompare : IEqualityComparer<Entity>
{
    public bool Equals(Entity a, Entity b)
    {
        var aCol = a.Columns.OrderBy(KeyValuePair => KeyValuePair.Key);
        var bCol = b.Columns.OrderBy(KeyValuePAir => KeyValuePAir.Key); 

        if (aCol.SequenceEqual(bCol))
            return true;
        else
            return false;           
    }

    public int GetHashCode(Entity obj)
    {
        return obj.Columns.GetHashCode(); 
    }
}

Je ne sais pas non plus sur l'implémentation de GethashCode.

Merci!

Était-ce utile?

La solution

Voici ce que je ferais:

    public bool Equals(Entity a, Entity b)
    {
        if (a.Columns.Count != b.Columns.Count)
            return false; // Different number of items

        foreach(var kvp in a.Columns)
        {
            object bValue;
            if (!b.Columns.TryGetValue(kvp.Key, out bValue))
                return false; // key missing in b
            if (!Equals(kvp.Value, bValue))
                return false; // value is different
        }
        return true;
    }

De cette façon, vous n'avez pas besoin de commander les entrées (qui est un O (n log n) opération): il vous suffit d'énumérer les entrées dans le premier dictionnaire (Sur)) et essayer de récupérer les valeurs par clé dans le deuxième dictionnaire (O (1)), donc la complexité globale est Sur).

Notez également que votre GetHashCode La méthode est incorrecte: dans la plupart des cas, il renverra différentes valeurs pour différentes instances de dictionnaire, même si elles ont le même contenu. Et si le code hash est différent, Equals ne s'appellera jamais ... vous avez plusieurs options pour l'implémenter correctement, aucun d'entre eux idéal:

  • Construisez le code de hash à partir du contenu du dictionnaire: serait la meilleure option, mais c'est lent, et GetHashCode doit être rapide
  • Renvoie toujours la même valeur, de cette façon Equals sera toujours appelé: très Mauvais si vous souhaitez utiliser ce comparateur dans un hachage / dictionnaire / hashset, car toutes les instances tomberont dans le même seau, entraînant Sur) accès au lieu de O (1)
  • retourner le Count du dictionnaire (comme suggéré par Digemall): il ne donnera pas une grande distribution, mais toujours mieux que de toujours renvoyer la même valeur, et il satisfait la contrainte pour GetHashCode (IE Les objets considérés comme égaux devraient avoir le même code de hash; deux dictionnaires "égaux" ont le même nombre d'éléments, donc ça marche)

Autres conseils

Quelque chose comme ça vient à l'esprit, mais il pourrait y avoir quelque chose de plus efficace:

public static bool Equals<TKey, TValue>(IDictionary<TKey, TValue> x, 
    IDictionary<TKey, TValue> y)
{
    return x.Keys.Intersect(y.Keys).Count == x.Keys.Count &&
        x.Keys.All(key => Object.Equals(x[key], y[key]));
}

Cela me semble bon, peut-être pas le plus rapide mais qui fonctionne.

Vous avez juste besoin de changer le GetHashCode implémentation qui est erronée.

Par exemple, vous pourriez revenir obj.Columns.Count.GetHashCode()

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top