创建IEqualityComparer <IEnumerable >

我正在使用xUnit,如果T是自定义类型,它无法确定2 IEnumerable是否相等。

我已经尝试过使用LINQ SequenceEqual但是由于T的实例不同,所以返回false;

这是一个使用非工作IEqualityComparer的基本测试

  [Fact] public void FactMethodName() { var one = new[] { new KeywordSchedule() { Id = 1 } }; var two = new[] { new KeywordSchedule() { Id = 1 } }; Assert.Equal(one, two, new KeywordScheduleComparer()); } public class KeywordScheduleComparer : IEqualityComparer<IEnumerable> { public bool Equals(IEnumerable x, IEnumerable y) { return Object.ReferenceEquals(x, y) || (x != null && y != null && x.SequenceEqual(y)); } public int GetHashCode(IEnumerable obj) { if (obj == null) return 0; return unchecked(obj.Select(e => e.GetHashCode()).Aggregate(0, (a, b) => a + b)); // BAD } } 

我在集成测试中使用它,所以我在开始时将数据从IEnumerable插入到数据库中,然后调用我的SUT从DB中检索数据并进行比较。

如果你能帮助我进行collections比较工作,我会很感激!

我刚刚validation了xUnit.net 1.9.2可以正常工作:

 public class MyClass { public int ID { get; set; } public string Name { get; set; } } public class MyClassComparer : IEqualityComparer { public bool Equals(MyClass x, MyClass y) { return x.ID == y.ID; } public int GetHashCode(MyClass obj) { return obj.ID.GetHashCode(); } } public class ExampleTest { [Fact] public void TestForEquality() { var obj1 = new MyClass { ID = 42, Name = "Brad" }; var obj2 = new MyClass { ID = 42, Name = "Joe" }; Assert.Equal(new[] { obj1 }, new[] { obj2 }, new MyClassComparer()); } } 

所以我不是100%清楚为什么你需要额外的比较器。 只需单个比较器即可。

那么,您的实施正在等待中。 您为IEnumerable实现了自定义比较器,但忘记为KeywordSchedule实现相同的。

x.SequenceEqual仍然使用Comparer.Default因此它用于引用comaprison,因此结果为false。

 public class KScheduleComparer : IEqualityComparer { public bool Equals(KeywordSchedule x, KeywordSchedule y) { return x.Id == y.Id; } public int GetHashCode(KeywordSchedule obj) { return obj.GetHashCode(); } } 

然后在KeywordScheduleComparer类中修改您的Equals方法,如下所示

 public class KeywordScheduleComparer : IEqualityComparer> { public bool Equals(IEnumerable x, IEnumerable y) { return Object.ReferenceEquals(x, y) || (x != null && y != null && x.SequenceEqual(y, new KScheduleComparer())); } public int GetHashCode(IEnumerable obj) { if (obj == null) return 0; return unchecked(obj.Select(e => e.GetHashCode()).Aggregate(0, (a, b) => a + b)); // BAD } } 

您可以使用FluentAssertions库更优雅地完成此操作 。 它有很多用于集合的断言方法。

 public class MyClass { public int ID { get; set; } public string Name { get; set; } protected bool Equals(MyClass other) { return ID == other.ID; } public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; if (obj.GetType() != GetType()) return false; return Equals((MyClass) obj); } public override int GetHashCode() { unchecked { return (ID*397) ^ (Name != null ? Name.GetHashCode() : 0); } } } public class ExampleTest { [Fact] public void TestForEquality() { var obj1 = new MyClass { ID = 42, Name = "Rock" }; var obj2 = new MyClass { ID = 42, Name = "Paper" }; var obj3 = new MyClass { ID = 42, Name = "Scissors" }; var obj4 = new MyClass { ID = 42, Name = "Lizard" }; var list1 = new List {obj1, obj2}; list1.Should().BeEquivalentTo(obj3, obj4); } }