Question

J'ai les cours suivants:

public class SupplierCategory : IEquatable<SupplierCategory>
{
    public string Name { get; set; }
    public string Parent { get; set; }

    #region IEquatable<SupplierCategory> Members

    public bool Equals(SupplierCategory other)
    {
        return this.Name == other.Name && this.Parent == other.Parent;
    }

    #endregion
}

public class CategoryPathComparer : IEqualityComparer<List<SupplierCategory>>
{
    #region IEqualityComparer<List<SupplierCategory>> Members

    public bool Equals(List<SupplierCategory> x, List<SupplierCategory> y)
    {
        return x.SequenceEqual(y);
    }

    public int GetHashCode(List<SupplierCategory> obj)
    {
        return obj.GetHashCode();
    }

    #endregion
}

Et j'utilise la requête linq suivante:

CategoryPathComparer comparer = new CategoryPathComparer();
List<List<SupplierCategory>> categoryPaths = (from i in infoList
                                                          select
                                                            new List<SupplierCategory>() { 
                                                             new SupplierCategory() { Name = i[3] },
                                                             new SupplierCategory() { Name = i[4], Parent = i[3] },
                                                             new SupplierCategory() { Name = i[5], Parent = i[4] }}).Distinct(comparer).ToList();

Mais le distinct ne fait pas ce que je veux, comme le montre le code suivant:

comp.Equals(categoryPaths[0], categoryPaths[1]); //returns True

Est-ce que j'utilise ceci de manière incorrecte? pourquoi ne sont-ils pas comparés comme je le souhaite?

Modifier: Pour démontrer que le comparateur fonctionne, les éléments suivants sont vrais, comme il se doit:

List<SupplierCategory> list1 = new List<SupplierCategory>() {
    new SupplierCategory() { Name = "Cat1" },
    new SupplierCategory() { Name = "Cat2", Parent = "Cat1" },
    new SupplierCategory() { Name = "Cat3", Parent = "Cat2" }
};
List<SupplierCategory> list1 = new List<SupplierCategory>() {
    new SupplierCategory() { Name = "Cat1" },
    new SupplierCategory() { Name = "Cat2", Parent = "Cat1" },
    new SupplierCategory() { Name = "Cat3", Parent = "Cat2" }
};
CategoryPathComparer comp = new CategoryPathComparer();
Console.WriteLine(comp.Equals(list1, list2).ToString());
Était-ce utile?

La solution

Votre problème est que vous n'avez pas implémenté IEqualityComparer correctement.

Lorsque vous implémentez IEqualityComparer<T> , vous doit mettre en œuvre GetHashCode de sorte que deux les objets ont le même hashcode.

Sinon, vous obtiendrez un comportement incorrect, comme vous le voyez ici.

Vous devez implémenter GetHashCode de la manière suivante: (avec l'aimable autorisation de cette réponse )

public int GetHashCode(List<SupplierCategory> obj) {
    int hash = 17;

    foreach(var value in obj)
        hash = hash * 23 + obj.GetHashCode();

    return hash;
}

Vous devez également remplacer SupplierCategory dans Equals pour être cohérent. Par exemple:

public override int GetHashCode() {
    int hash = 17;
    hash = hash * 23 + Name.GetHashCode();
    hash = hash * 23 + Parent.GetHashCode();
    return hash;
}

Enfin, bien que vous n'en ayez pas besoin, vous devez probablement remplacer IEquatable dans <=> et lui demander d'appeler la méthode <=> que vous avez implémentée pour <=>.

Autres conseils

En fait, ce problème est même traité dans la documentation: http://msdn.microsoft.com/en-us/library/bb338049. aspx .

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