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

查看:103
本文介绍了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<T>的不同实现.我有一个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天全站免登陆