IEnumerable.Except()和自定义比较器

1 c# linq iequatable iequalitycomparer linq-to-sql

我遇到了Except()方法的麻烦.它不返回差异,而是返回原始集合.

我已经尝试在Account类中实现IEquatable和IEqualityComparer.我也尝试为Account创建一个单独的IEqualityComparer类.

当从main调用Except()方法时,它似乎不会调用我的自定义Equals()方法,但是当我尝试Count()时,它确实调用了自定义的GetHashCode()方法!

我确定我在某个地方犯了一个小错误,我希望一双新眼睛可以帮助我.

主要:

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)));
Run Code Online (Sandbox Code Playgroud)

帐户:

    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*/
    }
Run Code Online (Sandbox Code Playgroud)

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);
        }
    }
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 6

基本上,LambdaComparer当您传入一个函数时,您的类就会被破坏,因为如果您不提供任何其他功能,它将使用"身份哈希码"提供程序.哈希代码被使用Except,这就是造成问题的原因.

这里有三个选择:

  1. 实现自己的ExceptBy方法然后最好将它贡献给包含那种东西的MoreLINQ.

  2. 使用不同的实现IEqualityComparer<T>.我有一个ProjectionEqualityComparer可以在MiscUtil中使用的类- 或者您可以使用在另一个问题中发布的代码.

  3. 将lambda表达式传递给您的LambdaComparer代码以用于哈希:

    new LambdaComparer<Account>((x, y) => x.IDPartner.Equals(y.IDPartner)),
                                x => x.IDPartner.GetHashCode());
    
    Run Code Online (Sandbox Code Playgroud)