使用 Linq 与自定义 IEqualityComparer 相交
长话短说:我有 2 个对象集合。一个包含好的值(我们称之为“Good”),另一个包含默认值(“Default”先生)。我想要良好和默认以及默认之间的并集。换句话说:相交(并集(Good,默认),默认)。人们可能会认为它解析为默认值,但这就是它变得棘手的地方:我使用自定义的 IEqualityComparer。
我有以下类:
class MyClass
{
public string MyString1;
public string MyString2;
public string MyString3;
}
class MyEqualityComparer : IEqualityComparer<MyClass>
{
public bool Equals(MyClass item1, MyClass item2)
{
if(item1 == null && item2 == null)
return true;
else if((item1 != null && item2 == null) ||
(item1 == null && item2 != null))
return false;
return item1.MyString1.Equals(item2.MyString1) &&
item1.MyString2.Equals(item2.MyString2);
}
public int GetHashCode(MyClass item)
{
return new { item.MyString1, item.MyString2 }.GetHashCode();
}
}
这是我的集合的特征 良好和默认集合:
默认:这是一个大集合,包含所有想要的 { MyString1, MyString2 } 对,但正如您可以猜到的那样,MyString3 值是默认值。
好:这是一个较小的集合,主要包含默认集中的项目,但也有一些好的 MyString3 值。它还具有一些不在所需集合范围内的 { MyString1, MyString2 }。
我想要做的是:仅获取 Good 中处于 Default 的项目,但将 Default 中的其他项目添加到其中。
我认为这是我最好的尝试:
HalfWantedResult = Good.Union(Default, new MyEqualityComparer());
WantedResult= HalfWantedResult.Intersect(Good, new MyEqualityComparer());
我教它应该有效,但我得到的结果基本上只是好的 { MyString1, MyString2 } 对集,但全部来自默认集,所以我有默认值整个价值。我还尝试切换最后一个相交的默认值和良好值,但得到相同的结果。
Long story short: I have 2 collections of objects. One contains good values (Let's call it "Good"), the other default values (Mr. "Default"). I want the Intersect of the Union between Good and Default, and Default. In other words: Intersect(Union(Good, Default), Default). One might think it resolves as Default, but here is where it gets tricky : I use a custom IEqualityComparer.
I got the following classes :
class MyClass
{
public string MyString1;
public string MyString2;
public string MyString3;
}
class MyEqualityComparer : IEqualityComparer<MyClass>
{
public bool Equals(MyClass item1, MyClass item2)
{
if(item1 == null && item2 == null)
return true;
else if((item1 != null && item2 == null) ||
(item1 == null && item2 != null))
return false;
return item1.MyString1.Equals(item2.MyString1) &&
item1.MyString2.Equals(item2.MyString2);
}
public int GetHashCode(MyClass item)
{
return new { item.MyString1, item.MyString2 }.GetHashCode();
}
}
Here are the characteristic of my collections Good and Default collections :
Default : It's a large set, containing all the wanted { MyString1, MyString2 } pairs, but the MyString3 values are, as you can guess, default values.
Good : It's a smaller set, containing mostly items which are in the Default set, but with some good MyString3 values. It also has some { MyString1, MyString2 } that are outside of the wanted set.
What I want to do is this : Take only the items from Good that are in Default, but add the other items in Default to that.
Here is, what I think is, my best try :
HalfWantedResult = Good.Union(Default, new MyEqualityComparer());
WantedResult= HalfWantedResult.Intersect(Good, new MyEqualityComparer());
I taught it should have worked, but the result I get is basically only the good { MyString1, MyString2 } pairs set, but all coming from the Default set, so I have the default value all across. I also tried switching the Default and Good of the last Intersect, but I get the same result.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
首先,这是错误的:
如果哈希码不同,则确定对应的两个项目不同,但如果它们相等,则不能保证对应的两个项目相等。
所以这是正确的
Equals
实现:如 休闲裤建议(期待着我)代码如下:
First of all this is wrong:
If the hashcode's are different for sure the corresponding 2 items are different, but if they're equal is not guaranteed that the corresponding 2 items are equal.
So this is the correct
Equals
implementation:As Slacks suggested (anticipating me) the code is the following:
您需要检查实际的相等性,而不仅仅是哈希码相等性。
GetHashCode()
不是(也不可能)无冲突,这就是为什么首先需要Equals
方法的原因。另外,您可以通过编写更简单的方法来完成此操作。
Distinct
方法将返回每对重复项的第一项,因此这将返回所需的结果。编辑:应该是
You need to check for actual equality, not just hashcode equality.
GetHashCode()
is not (and cannot be) collision free, which is why theEquals
method is required in the first place.Also, you can do this much more simply by writing
The
Distinct
method will return the first item of each pair of duplicates, so this will return the desired result.EDIT: That should be