2009-08-19 11 views
1

Ich habe Probleme mit der Except() -Methode. Anstatt die Differenz zurückzugeben, wird die ursprüngliche Menge zurückgegeben.IEnumerable.Except() und ein benutzerdefinierter Vergleich

Ich habe versucht, IEquatable und IEqualityComparer in der Account-Klasse zu implementieren. Ich habe auch versucht, eine separate IEqualityComparer-Klasse für Account zu erstellen.

Wenn die Except() -Methode von Main aufgerufen wird, scheint es nicht meine benutzerdefinierte Equals() -Methode aufzurufen, aber wenn ich Count() versuchte, rief es die benutzerdefinierte GetHashCode() -Methode!

Ich bin mir sicher, dass ich irgendwo einen trivialen Fehler gemacht habe und ich hoffe, dass mir ein neues Paar Augen helfen kann.

Haupt:

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))); 

Konto:

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); 
     } 
    } 

Antwort

6

Grundsätzlich Ihre LambdaComparer Klasse gebrochen wird, wenn Sie in nur einer einzigen Funktion übergeben, weil es die verwendet "identity hash code" Anbieter, wenn Sie nichts anderes angeben. Der Hash-Code wird von Except verwendet, und das verursacht das Problem.

Drei Möglichkeiten:

  1. Ihre eigene ExceptBy Methode implementieren und es dann zu MoreLINQ vorzugsweise beitragen, die diese Art von Dingen enthalten. Verwenden Sie eine andere Implementierung von IEqualityComparer<T>. Ich habe eine ProjectionEqualityComparer Klasse, die Sie in MiscUtil verwenden können - oder Sie können den Code as posted in another question verwenden.

  2. Geben Sie einen Lambda-Ausdruck in Ihren LambdaComparer Code für den Hash zu verwenden:

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

Sie könnten auch so geliefert werden nur die Gleichheit Parameter, wenn schnell Ihre LambdaComparer beheben zu arbeiten:

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