联合两个自定义类会返回重复项
我有两个自定义类, ChangeRequest
和ChangeRequests
,其中ChangeRequests
可以包含许多ChangeRequest
实例。
public class ChangeRequests : IXmlSerializable, ICloneable, IEnumerable, IEquatable { ... } public class ChangeRequest : ICloneable, IXmlSerializable, IEquatable { ... }
我试图做两个ChangeRequests
实例的联合。 但是,似乎没有删除重复项。 我的MSTestunit testing如下:
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(crs2)); ChangeRequests expected = crs2.Clone(); Assert.AreEqual(expected, unionedCRs, "Duplicates should be removed from a Union");
测试在最后一行失败, unionedCRs
包含两个unionedCRs
副本。 当我尝试调试并逐步执行每一行时,我在第一行的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(other); }
这里是ChangeRequests.Equals(object)
:
public override bool Equals(object obj) { return Equals(obj as ChangeRequests); }
编辑:我在ChangeRequest
和ChangeRequests
上覆盖GetHashCode
,但仍然在我的测试中,如果我执行IEnumerable unionedCRsIEnum = crs1.Union(crs2);
, unionedCRsIEnum
最终得到两份带有CRID
12的ChangeRequest
副本。
编辑:因为Assert.AreEqual(expected, unionedCRs.Distinct(), "Distinct should remove duplicates");
某些东西必须在我的Equals
或GetHashCode
实现的某处Assert.AreEqual(expected, unionedCRs.Distinct(), "Distinct should remove duplicates");
如果失败了, unionedCRs.Distinct()
和unionedCRs.Distinct()
的字符串表示显示unionedCRs.Distinct()
肯定有两个CR 12副本。
确保您的GetHashCode
实现与您的Equals
一致 – Enumerable.Union
方法似乎确实使用了两者。
如果你已经实现了一个而不是另一个,你应该从编译器得到警告; 你仍然需要确保两种方法相互一致。 以下是规则的简单摘要: 为什么在重写Equals方法时重写GetHashCode很重要?
我不相信Assert.AreEqual()
检查序列的内容 – 它比较序列对象本身,这显然是不相等的。
你想要的是一个SequenceEqual()
方法,它将实际检查两个序列的内容。 这个答案可能对你有帮助 。 这是对类似问题的回答,描述了如何与IEnumerable<>
序列进行比较。
您可以轻松获取响应者的答案,并创建一个扩展方法,使调用看起来更像断言:
public static class AssertionExt { public static bool AreSequencesEqual( IEnumerable expected, IEnumerable sequence ) { Assert.AreEqual(expected.Count(), sequence .Count()); IEnumerator e1 = expected.GetEnumerator(); IEnumerator e2 = sequence .GetEnumerator(); while (e1.MoveNext() && e2.MoveNext()) { Assert.AreEqual(e1.Current, e2.Current); } } }
或者,您可以使用SequenceEqual()
来比较序列,意识到它不会提供有关哪些元素不相等的任何信息。
正如LBushkin所说, Assert.AreEqual
只会在序列上调用Equals
。
您可以使用SequenceEqual
扩展方法:
Assert.IsTrue(expected.SequenceEqual(unionedCRs));
但是,如果失败,那将不会提供太多信息。
您可能希望使用我们为MoreLINQ编写的测试代码,这些代码是以序列为中心的 – 如果序列不相等,它将以不同的方式指定它们。 (我正在尝试获取有问题的源文件的链接,但我的网络连接是垃圾。)
上述就是C#学习教程:联合两个自定义类会返回重复项分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/959848.html