【问题标题】:Comparing two List<MyClass>: How to find out difference?比较两个 List<MyClass>:如何找出差异?
【发布时间】:2011-12-07 12:53:47
【问题描述】:

我曾经像这样比较列表,但在测试中返回 false:

Assert.IsTrue(expected.SequenceEquals(actual));

并尝试转换为 json 并且成功了:

Assert.AreEqual(expected.ToJson(), actual.ToJson());

值似乎相等,有什么不同?如何找出列表中的不同之处?

更新:

我的班级:

public class Department
{
    [BsonId]
    public ObjectId Id { get; set; }    
    public string Name { get; set; }            

    public override string ToString()
    {
        return Id.ToString();
    }
}

【问题讨论】:

  • 您需要检查序列是否只包含相同的元素,或者也包含相同的顺序?
  • 我只需要比较值。但有趣的是:为什么当对象的值相等时,列表中的顺序相等,SequenceEquals 返回 false。
  • @1gn1ter: Enumerable.SequenceEqual() 使用EqualityComparer&lt;T&gt;.Default 比较项目,这可能是原因。
  • 原因是您的比较器正在比较对您的对象的引用,而不是值。您需要覆盖 Equals (etc) 以获得所需的功能。或者,您可以逐个字段进行比较。

标签: c# .net unit-testing mstest mongodb-.net-driver


【解决方案1】:

如果MyClass 实现IEquatable&lt;MyClass&gt;,那么试试这个:

expected.Sort(); 
actual.Sort();
if (Enumerable.SequenceEqual(actual, expected)) { ... }

如果它没有实现IEquatable,那么你可能会遇到奇怪的行为,因为对象引用将在两个列表中进行比较,而不是它们的字段:

using System;
using System.Collections.Generic;
using System.Linq;

public class MyClassA
{
  private int i;
  public MyClassA(int i) { this.i = i; }
}

public class MyClassB : IEquatable<MyClassB>
{
  private int i;
  public MyClassB(int i) { this.i = i; }
  public bool Equals(MyClassB other) { return this.i == other.i; }
}

public class Program
{
  public static void Main()
  {
    var actual1 = new List<MyClassA>() { new MyClassA(1), new MyClassA(2), new MyClassA(3) };
    var expected1 = new List<MyClassA>() { new MyClassA(1), new MyClassA(2), new MyClassA(3) };
    Console.WriteLine(Enumerable.SequenceEqual(actual1, expected1));

    var a1 = new MyClassA(1);
    var a2 = new MyClassA(2);
    var a3 = new MyClassA(3);
    var actual2 = new List<MyClassA>() { a1, a2, a3 };
    var expected2 = new List<MyClassA>() { a1, a2, a3 };
    Console.WriteLine(Enumerable.SequenceEqual(actual2, expected2));

    var actual3 = new List<MyClassB>() { new MyClassB(1), new MyClassB(2), new MyClassB(3) };
    var expected3 = new List<MyClassB>() { new MyClassB(1), new MyClassB(2), new MyClassB(3) };
    Console.WriteLine(Enumerable.SequenceEqual(actual3, expected3));

    var actual4 = new List<MyClassB>() { new MyClassB(1), new MyClassB(2), new MyClassB(3) };
    var expected4 = new List<MyClassB>() { new MyClassB(3), new MyClassB(2), new MyClassB(1) };
    Console.WriteLine(Enumerable.SequenceEqual(actual4, expected4));
  }
}

输出:

False
True
True
False

【讨论】:

  • 是的,OP 的主要问题是:他的T 是什么?
  • T 是我的自定义类,它只有属性并覆盖 ToString() 我可以发布该类的代码
  • @1gn1ter:请发布您的列表内容。
  • 谢谢,科尔。我已经实现了 IEquatable,现在它可以正常工作了。
【解决方案2】:
using System.Linq;

Enumerable.SequenceEqual(a, b);

// or SequenceEqual(a, b, StringComparer.OrdinalIgnoreCase)

MSDN,另见this question

【讨论】:

  • 和预期一样。SequenceEquals(actual)
【解决方案3】:

也许你可以使用 IEnumerable.ExceptOf

http://msdn.microsoft.com/en-us/library/bb300779.aspx

我们也许可以使用 HashSet 和 intersect 方法。 http://msdn.microsoft.com/en-us/library/bb293080.aspx

【讨论】:

  • 除了方法,也给出了不同的对象。而对象的值是相同的。
【解决方案4】:

我倾向于找到适合这种用途的 HashSet&lt;T&gt; 集合,将您的集合转换为 HashSet&lt;T&gt; 然后调用 SetEquals

【讨论】:

    猜你喜欢
    • 2019-07-19
    • 2023-03-07
    • 1970-01-01
    • 2017-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多