【发布时间】:2010-06-28 16:00:55
【问题描述】:
我有两个自定义类,ChangeRequest 和 ChangeRequests,其中一个 ChangeRequests 可以包含许多 ChangeRequest 实例。
public class ChangeRequests : IXmlSerializable, ICloneable, IEnumerable<ChangeRequest>,
IEquatable<ChangeRequests> { ... }
public class ChangeRequest : ICloneable, IXmlSerializable, IEquatable<ChangeRequest>
{ ... }
我正在尝试合并两个 ChangeRequests 实例。但是,似乎没有删除重复项。我的 MSTest 单元测试如下:
var cr1 = new ChangeRequest { CRID = "12" };
var crs1 = new ChangeRequests { cr1 };
var crs2 = new ChangeRequests
{
cr1.Clone(),
new ChangeRequest { CRID = "34" }
};
Assert.AreEqual(crs1[0], crs2[0], "First CR in both ChangeRequests should be equal");
var unionedCRs = new ChangeRequests(crs1.Union<ChangeRequest>(crs2));
ChangeRequests expected = crs2.Clone();
Assert.AreEqual(expected, unionedCRs, "Duplicates should be removed from a Union");
测试在最后一行失败,unionedCRs 包含两个cr1 的副本。当我尝试调试并单步执行每一行时,我在第一行的ChangeRequest.Equals(object) 和ChangeRequest.Equals(ChangeRequest) 的第一行都有一个断点,但都没有命中。为什么联合包含重复的ChangeRequest 实例?
编辑:按要求,这里是ChangeRequests.Equals(ChangeRequests):
public bool Equals(ChangeRequests other)
{
if (ReferenceEquals(this, other))
{
return true;
}
return null != other && this.SequenceEqual<ChangeRequest>(other);
}
这里是ChangeRequests.Equals(object):
public override bool Equals(object obj)
{
return Equals(obj as ChangeRequests);
}
编辑: 我在ChangeRequest 和ChangeRequests 上都覆盖了GetHashCode,但仍然在我的测试中,如果我这样做IEnumerable<ChangeRequest> unionedCRsIEnum = crs1.Union<ChangeRequest>(crs2);,unionedCRsIEnum 最终会得到@ 的两个副本987654342@ 与CRID 12。
编辑: 我的Equals 或GetHashCode 实现必须在某处出现问题,因为Assert.AreEqual(expected, unionedCRs.Distinct(), "Distinct should remove duplicates"); 失败,而expected 和unionedCRs.Distinct() 的字符串表示表明@ 987654349@ 肯定有两份 CR 12。
【问题讨论】:
-
你能发布你对
ChangeRequests.Equals和ChangeRequests.GetHashCode的实现吗?很容易在其中一个中打错字并破坏对象身份。 -
@Tim:我在我的问题中添加了
ChangeRequests.Equals的两个实现,但我没有覆盖GetHashCode...也许我应该这样做! -
对,您的
GetHashCode需要与您的Equals保持一致 -Union方法似乎同时使用两者。 -
您绝对应该重写 GetHashCode。我很惊讶编译器还没有警告过你。
-
@Tim:你应该发布你的“修复
GetHashCode”建议作为答案——我会选择它作为选择的!原来这是一个GetHashCode问题。Union现在按预期工作。 :)