IEnumerable.Except() 和自定义比较器
我在使用 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)));
帐户:
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);
}
}
I'm having troubles with the Except() method.
Instead of returning the difference, it returns the original set.
I've tried implementing the IEquatable and IEqualityComparer in the Account class.
I've also tried creating a separate IEqualityComparer class for Account.
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.
main:
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)));
Account:
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);
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
基本上,当您仅传入一个函数时,您的 LambdaComparer 类就会被破坏,因为如果您不提供其他任何内容,它就会使用“身份哈希代码”提供程序。哈希码由
Except
使用,这就是导致问题的原因。这里有三个选项:
实现您自己的
ExceptBy
方法,然后最好将其贡献给 MoreLINQ 包含此类内容。使用
IEqualityComparer
的不同实现。我有一个ProjectionEqualityComparer
类,您可以在 MiscUtil 中使用 - 或者您可以使用另一个问题中发布的代码。< /p>将 lambda 表达式传递到您的
LambdaComparer
代码中以用于哈希: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 byExcept
, and that's what's causing the problem.Three options here:
Implement your own
ExceptBy
method and then preferably contribute it to MoreLINQ which contains that sort of thing.Use a different implementation of
IEqualityComparer<T>
. I have aProjectionEqualityComparer
class you can use in MiscUtil - or you can use the code as posted in another question.Pass a lambda expression into your
LambdaComparer
code to use for the hash:您还可以快速修复 LambdaComparer,使其在仅提供相等参数时正常工作,如下所示:
You could also quickly fix your LambdaComparer to work when only the equality parameters are supplied like this:
看这里,如何通过 linq.Except 及其他方式使用和实现 IEqualityComparer。
https://www.dreamincode .net/forums/topic/352582-linq-by-example-3-methods-using-iequalitycomparer/
}
公共类 DepartmentComparer : IEqualityComparer {
}
Look here, how to use and implementing IEqualityComparer in way with linq.Except and beyond.
https://www.dreamincode.net/forums/topic/352582-linq-by-example-3-methods-using-iequalitycomparer/
}
public class DepartmentComparer : IEqualityComparer {
}
IMO,与此问题的其他解决方案相比,上面的答案是最简单的解决方案。我对其进行了调整,以便对 Object 类的 Equals() 和 GetHasCode() 使用相同的逻辑。好处是这个解决方案对于客户端 linq 表达式是完全透明的。
IMO, this answer above is the simplest solution compared to other solutions for this problem. I tweaked it such that I use the same logic for the Object class's Equals() and GetHasCode(). The benefit is that this solution is completely transparent to the client linq expression.