2009-07-01 11 views
29

J'ai ceIEqualityComparer pour le type anonyme

var n = ItemList.Select(s => new { s.Vchr, s.Id, s.Ctr, s.Vendor, s.Description, s.Invoice }).ToList(); 
n.AddRange(OtherList.Select(s => new { s.Vchr, s.Id, s.Ctr, s.Vendor, s.Description, s.Invoice }).ToList();); 

Je voudrais le faire si elle lorsque cela est autorisé

n = n.Distinct((x, y) => x.Vchr == y.Vchr)).ToList(); 

J'ai essayé d'utiliser le LambdaComparer générique, mais depuis im en utilisant des types anonymes il n'y a pas de type l'associer avec.

« Aidez-moi Obi Wan Kenobi, vous êtes mon seul espoir »

+3

Bonne question, je cherchais juste la même chose. Incroyable ce n'est pas dans la bibliothèque standard. – orip

+0

Il pourrait aider [Envelopper un délégué dans un IEqualityComparer] (http://stackoverflow.com/questions/98033/wrap-a-delegate-in-an-iequalitycomparer) – marbel82

Répondre

16

L'astuce est de créer un comparateur qui ne fonctionne que sur les types inférées. Par exemple:

public class Comparer<T> : IComparer<T> { 
    private Func<T,T,int> _func; 
    public Comparer(Func<T,T,int> func) { 
    _func = func; 
    } 
    public int Compare(T x, T y) { 
    return _func(x,y); 
    } 
} 

public static class Comparer { 
    public static Comparer<T> Create<T>(Func<T,T,int> func){ 
    return new Comparer<T>(func); 
    } 
    public static Comparer<T> CreateComparerForElements<T>(this IEnumerable<T> enumerable, Func<T,T,int> func) { 
    return new Comparer<T>(func); 
    } 
} 

Maintenant, je peux faire ce qui suit ... solution aki:

var comp = n.CreateComparerForElements((x, y) => x.Vchr == y.Vchr); 
+0

Très lisse. Im pensant cependant que dans l'intérêt de l'écriture de code propre, je devrais créer une interface à utiliser comme T dans un IEqualityComparer . – kjgilla

+0

Je ne pouvais pas obtenir par le problème. Voir ci-dessous. – Tormod

3

La plupart du temps lorsque vous comparez (pour l'égalité ou tri) vous êtes intéressés à choisir les clés pour comparer par, pas la méthode d'égalité ou de comparaison elle-même (c'est l'idée derrière l'API de tri de liste de Python).

Il existe un exemple de comparateur d'égalité de clé here.

0

Je note que la réponse de JaredPar ne répond pas tout à fait à la question puisque les méthodes d'ensemble comme Distinct et Except exigent un IEqualityComparer<T> pas un IComparer<T>. Ce qui suit suppose qu'un IEquatable aura un GetHashCode approprié, et il a certainement une méthode Equals appropriée.

public class GeneralComparer<T, TEquatable> : IEqualityComparer<T> 
{ 
    private readonly Func<T, IEquatable<TEquatable>> equatableSelector; 

    public GeneralComparer(Func<T, IEquatable<TEquatable>> equatableSelector) 
    { 
     this.equatableSelector = equatableSelector; 
    } 

    public bool Equals(T x, T y) 
    { 
     return equatableSelector.Invoke(x).Equals(equatableSelector.Invoke(y)); 
    } 

    public int GetHashCode(T x) 
    { 
     return equatableSelector(x).GetHashCode(); 
    } 
} 

public static class GeneralComparer 
{ 
    public static GeneralComparer<T, TEquatable> Create<T, TEquatable>(Func<T, TEquatable> equatableSelector) 
    { 
     return new GeneralComparer<T, TEquatable>(equatableSelector); 
    } 
} 

Lorsque la même inférence d'un tour de classe statique est utilisée comme dans la réponse de JaredPar.

Pour être plus général, vous pouvez fournir deux Func s: un Func<T, T, bool> pour vérifier l'égalité et Func<T, T, int> pour sélectionner un code de hachage.

+0

Bien que la réponse de JaredPar soit à propos de la comparaison, elle donne l'idée d'aller plus loin. – nawfal

Questions connexes