IEnumerable.Except() 和自定义比较器 [英] IEnumerable.Except() and a custom comparer

查看:19
本文介绍了IEnumerable.Except() 和自定义比较器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在使用 except() 方法时遇到了麻烦.它没有返回差值,而是返回原始集合.

I'm having troubles with the Except() method. Instead of returning the difference, it returns the original set.

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

I've tried implementing the IEquatable and IEqualityComparer in the Account class. I've also tried creating a separate IEqualityComparer class for Account.

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

When the Except() method is called from main, it doesn't seem to call my custom Equals() method, but when I tried Count(), it did call the custom GetHashCode() method!

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

I'm sure I made a trivial mistake somewhere and I hope a fresh pair of eyes can help me.

主要:

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

帐户:

    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:

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

推荐答案

当你只传入一个函数时,基本上你的 LambdaComparer 类被破坏了,因为它使用身份哈希码"提供者,如果你不提供任何其他东西.Except 使用了哈希码,这就是导致问题的原因.

Basically your LambdaComparer class is broken when you pass in just a single function, because it uses the "identity hash code" provider if you don't provide anything else. The hash code is used by Except, and that's what's causing the problem.

这里有三个选项:

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

  1. Implement your own ExceptBy method and then preferably contribute it to MoreLINQ which contains that sort of thing.

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

Use a different implementation of IEqualityComparer<T>. I have a ProjectionEqualityComparer class you can use in MiscUtil - or you can use the code as posted in another question.

将 lambda 表达式传递到您的 LambdaComparer 代码中以用于哈希:

Pass a lambda expression into your LambdaComparer code to use for the hash:

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

这篇关于IEnumerable.Except() 和自定义比较器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆