IEnumerable.Except()和一个自定义比较器 [英] IEnumerable.Except() and a custom comparer
问题描述
我在使用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.
这里有三个选项:
-
实施您自己的
ExceptBy
方法,然后最好将其贡献给 MoreLINQ 其中包含此类内容.
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屋!