长话短说:我有2个对象集合。一个包含好的值(让我们称之为“好”),其他默认值(先生“默认”)。我希望联盟的相交在良好和默认之间,以及默认。换句话说:相交(联合(良好,默认),默认)。有人可能认为它解析为默认值,但这里是棘手的:我使用自定义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();
}
}
以下是我的收藏品Good和Default集合的特征:
默认值:它是一个很大的集合,包含所有想要的{MyString1,MyString2}对,但是你可以猜测,MyString3值是默认值。
好:它是一个较小的集合,主要包含默认集合中的项目,但具有一些好的MyString3值。它还有一些{MyString1,MyString2},它们位于想要的集合之外。
我想要做的是:只接受来自Good的物品,这些物品属于默认值,但将Default中的其他物品添加到其中。
以下是我认为最好的尝试:
HalfWantedResult = Good.Union(Default, new MyEqualityComparer());
WantedResult= HalfWantedResult.Intersect(Good, new MyEqualityComparer());
我教它应该有用,但我得到的结果基本上只是好的{MyString1,MyString2}对设置,但都来自默认设置,所以我有所有的默认值。我也试过切换最后一个Intersect的Default和Good,但是得到了相同的结果。
答案 0 :(得分:19)
首先,这是错误的:
public bool Equals(MyClass item1, MyClass item2)
{
return GetHashCode(item1) == GetHashCode(item2);
}
如果哈希码是不同的,相应的2个项目是不同的,但是如果它们相等则不能保证相应的2项是相等的。
所以这是正确的Equals
实现:
public bool Equals(MyClass item1, MyClass item2)
{
if(object.ReferenceEquals(item1, item2))
return true;
if(item1 == null || item2 == null)
return false;
return item1.MyString1.Equals(item2.MyString1) &&
item1.MyString2.Equals(item2.MyString2);
}
作为Slacks suggested(期待我),代码如下:
var Default = new List<MyClass>
{
new MyClass{MyString1="A",MyString2="A",MyString3="-"},
new MyClass{MyString1="B",MyString2="B",MyString3="-"},
new MyClass{MyString1="X",MyString2="X",MyString3="-"},
new MyClass{MyString1="Y",MyString2="Y",MyString3="-"},
new MyClass{MyString1="Z",MyString2="Z",MyString3="-"},
};
var Good = new List<MyClass>
{
new MyClass{MyString1="A",MyString2="A",MyString3="+"},
new MyClass{MyString1="B",MyString2="B",MyString3="+"},
new MyClass{MyString1="C",MyString2="C",MyString3="+"},
new MyClass{MyString1="D",MyString2="D",MyString3="+"},
new MyClass{MyString1="E",MyString2="E",MyString3="+"},
};
var wantedResult = Good.Intersect(Default, new MyEqualityComparer())
.Union(Default, new MyEqualityComparer());
// wantedResult:
// A A +
// B B +
// X X -
// Y Y -
// Z Z -
答案 1 :(得分:10)
您需要检查实际的相等性,而不仅仅是哈希码相等。
GetHashCode()
不是(也不可能)无冲突,这就是首先需要Equals
方法的原因。
此外,您可以通过编写
来更简单地完成此操作WantedResult = Good.Concat(Default).Distinct();
Distinct
方法将返回每对重复项的第一项,因此这将返回所需的结果。
编辑:那应该是
WantedResult = Good.Intersect(Default, new MyEqualityComparer())
.Union(Default, new MyEqualityComparer());