2009-08-19 5 views
1

J'ai des problèmes avec la méthode Except(). Au lieu de renvoyer la différence, il renvoie l'ensemble d'origine.IEnumerable.Except() et un comparateur personnalisé

J'ai essayé d'implémenter IEquatable et IEqualityComparer dans la classe Account. J'ai également essayé de créer une classe IEqualityComparer séparée pour Account. Lorsque la méthode Except() est appelée à partir de main, elle ne semble pas appeler ma méthode Equals() personnalisée, mais lorsque j'ai essayé Count(), elle a appelé la méthode personnalisée GetHashCode()!

Je suis sûr que j'ai fait une erreur triviale quelque part et j'espère qu'une nouvelle paire d'yeux peut m'aider.

principale:

IEnumerable<Account> everyPartnerID = 
    from partner in dataContext.Partners 
    select new Account { IDPartner = partner.ID, Name = partner.Name }; 


IEnumerable<Account> hasAccountPartnerID = 
    from partner in dataContext.Partners 
    from account in dataContext.Accounts 
    where 
     !partner.ID.Equals(Guid.Empty) && 
     account.IDPartner.Equals(partner.ID) && 
     account.Username.Equals("Special") 
    select new Account { IDPartner = partner.ID, Name = partner.Name }; 

IEnumerable<Account> noAccountPartnerID = 
    everyPartnerID.Except(
     hasAccountPartnerID, 
     new LambdaComparer<Account>((x, y) => x.IDPartner.Equals(y.IDPartner))); 

compte:

public class Account : IEquatable<Account> 
    { 
     public Guid IDPartner{ get; set; } 
     public string Name{ get; set; } 

/*  #region IEquatable<Account> Members 

     public bool Equals(Account other) 
     { 
      return this.IDPartner.Equals(other.IDPartner); 
     } 

     #endregion*/ 
    } 

LambdaComparer:

public class LambdaComparer<T> : IEqualityComparer<T> 
    { 
     private readonly Func<T, T, bool> _lambdaComparer; 
     private readonly Func<T, int> _lambdaHash; 

     public LambdaComparer(Func<T, T, bool> lambdaComparer) : 
      this(lambdaComparer, o => o.GetHashCode()) 
     { 
     } 

     public LambdaComparer(Func<T, T, bool> lambdaComparer, Func<T, int> lambdaHash) 
     { 
      if (lambdaComparer == null) 
       throw new ArgumentNullException("lambdaComparer"); 
      if (lambdaHash == null) 
       throw new ArgumentNullException("lambdaHash"); 

      _lambdaComparer = lambdaComparer; 
      _lambdaHash = lambdaHash; 
     } 

     public bool Equals(T x, T y) 
     { 
      return _lambdaComparer(x, y); 
     } 

     public int GetHashCode(T obj) 
     { 
      return _lambdaHash(obj); 
     } 
    } 

Répondre

6

Fondamentalement votre classe LambdaComparer est brisé lorsque vous passez dans une seule fonction, car elle utilise la fournisseur de "code de hachage d'identité" si vous ne fournissez rien d'autre. Le code de hachage est utilisé par Except, et c'est ce qui cause le problème.

Trois options:

  1. Mettre en oeuvre votre propre méthode ExceptBy et contribuent de préférence à MoreLINQ qui contient ce genre de chose. Utilisez une implémentation différente de IEqualityComparer<T>. J'ai une classe ProjectionEqualityComparer que vous pouvez utiliser dans MiscUtil - ou vous pouvez utiliser le code as posted in another question.

  2. passer d'expression lambda dans votre code LambdaComparer à utiliser pour le hachage:

    new LambdaComparer<Account>((x, y) => x.IDPartner.Equals(y.IDPartner)), 
              x => x.IDPartner.GetHashCode()); 
    
1

Vous pouvez également fixer rapidement votre LambdaComparer travailler lorsque seuls les paramètres d'égalité sont fournis comme ceci:

public LambdaComparer(Func<T, T, bool> lambdaComparer) : 
     this(lambdaComparer, o => 1) 
    { 
    } 
Questions connexes