代码之家  ›  专栏  ›  技术社区  ›  Sarah Vessels

合并两个自定义类将返回重复的

  •  3
  • Sarah Vessels  · 技术社区  · 15 年前

    我有两个定制课程, ChangeRequest ChangeRequests 更改请求 可以包含许多 实例。

    public class ChangeRequests : IXmlSerializable, ICloneable, IEnumerable<ChangeRequest>,
        IEquatable<ChangeRequests> { ... }
    
    public class ChangeRequest : ICloneable, IXmlSerializable, IEquatable<ChangeRequest>
        { ... }
    

    我在试着做两个人的结合 实例。但是,似乎没有删除重复项。我的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) ,但两人都没有被击中。为什么联合体包含重复项

    编辑: 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);
    }
    

    编辑: 我越界了 GetHashCode 两边都有 但还是在我的测试中,如果我做的话 IEnumerable<ChangeRequest> unionedCRsIEnum = crs1.Union<ChangeRequest>(crs2); , unionedCRsIEnum 更改请求 具有 CRID

    编辑: 一定是我的问题 Equals 方法 Assert.AreEqual(expected, unionedCRs.Distinct(), "Distinct should remove duplicates"); 失败,并且 expected unionedCRs.Distinct() 给我看看 unionedCRs.Distinct() 肯定有两份CR12。

    3 回复  |  直到 15 年前
        1
  •  4
  •   Community CDub    8 年前

    确保您的 GetHashCode 执行与您的 Equals Enumerable.Union 方法似乎两者都使用。

    如果你实现了其中一个而没有实现另一个,你应该从编译器那里得到一个警告;还是要由你来确定这两种方法是否一致。下面是一个方便的规则摘要: Why is it important to override GetHashCode when Equals method is overridden?

        2
  •  3
  •   Community CDub    8 年前

    我不相信 Assert.AreEqual() 内容

    你想要的是 SequenceEqual() 方法,它将实际检查两个序列的内容。 This answer may help you . 这是对一个类似问题的回答,描述了如何与 IEnumerable<>

    public static class AssertionExt
    {
      public static bool AreSequencesEqual<T>( IEnumerable<T> expected, 
                                               IEnumerable<T> sequence )
      {
        Assert.AreEqual(expected.Count(), sequence .Count()); 
    
        IEnumerator<Token> e1 = expected.GetEnumerator(); 
        IEnumerator<Token> e2 = sequence .GetEnumerator(); 
    
        while (e1.MoveNext() && e2.MoveNext()) 
        { 
            Assert.AreEqual(e1.Current, e2.Current); 
        }
      }
    }
    

    或者你可以用 SequenceEqual() ,来比较序列,意识到它不会提供任何关于 哪一个 元素不相等。

        3
  •  0
  •   Jon Skeet    15 年前

    Assert.AreEqual 我会打电话的 Equals 在序列上。

    你可以用 SequenceEqual 扩展方法:

    Assert.IsTrue(expected.SequenceEqual(unionedCRs));
    

    然而,如果失败了,这并不能提供多少信息。

    你可以使用 test code we wrote for MoreLINQ 这是序列聚焦-如果序列不相等,它将指定它们以什么方式不同(我正试图获取到有问题的源文件的链接,但我的网络连接是垃圾。)