首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >创建IEqualityComparer<IEnumerable<T>>

创建IEqualityComparer<IEnumerable<T>>
EN

Stack Overflow用户
提问于 2013-09-10 21:41:05
回答 3查看 12.2K关注 0票数 7

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

我尝试过使用LINQ SequenceEqual,但由于T的实例不同,因此返回false;

下面是一个不起作用的IEqualityComparer的基本测试

代码语言:javascript
复制
    [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<KeywordSchedule>>
{
    public bool Equals(IEnumerable<KeywordSchedule> x, IEnumerable<KeywordSchedule> y)
    {
        return Object.ReferenceEquals(x, y) || (x != null && y != null && x.SequenceEqual(y));
    }

    public int GetHashCode(IEnumerable<KeywordSchedule> obj)
    {
        if (obj == null)
            return 0;

        return unchecked(obj.Select(e => e.GetHashCode()).Aggregate(0, (a, b) => a + b));  // BAD
    }
}

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

如果你能帮我做一个集合比较,我将不胜感激!

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-09-11 00:16:14

我刚刚验证了这在xUnit.net 1.9.2中工作得很好:

代码语言:javascript
复制
public class MyClass
{
    public int ID { get; set; }
    public string Name { get; set; }
}

public class MyClassComparer : IEqualityComparer<MyClass>
{
    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%清楚为什么你需要额外的比较器。只需要一个比较器就足够了。

票数 15
EN

Stack Overflow用户

发布于 2013-09-10 22:04:30

嗯,你的实现还在等待中。您为IEnumerable<KeywordSchedule>实现了自定义比较器,但忘记了为KeywordSchedule实现相同的比较器。

x.SequenceEqual仍然使用Comparer<T>.Default,所以它用于引用比较,因此结果是假的。

代码语言:javascript
复制
public class KScheduleComparer : IEqualityComparer<KeywordSchedule>
{
    public bool Equals(KeywordSchedule x, KeywordSchedule y)
    {
        return x.Id == y.Id;                
    }

    public int GetHashCode(KeywordSchedule obj)
    {
        return obj.GetHashCode();
    }
}

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

代码语言:javascript
复制
public class KeywordScheduleComparer : IEqualityComparer<IEnumerable<KeywordSchedule>>
{
    public bool Equals(IEnumerable<KeywordSchedule> x, IEnumerable<KeywordSchedule> y)
    {
        return Object.ReferenceEquals(x, y) || (x != null && y != null && x.SequenceEqual(y, new KScheduleComparer()));
    }

    public int GetHashCode(IEnumerable<KeywordSchedule> obj)
    {
        if (obj == null)
            return 0;

        return unchecked(obj.Select(e => e.GetHashCode()).Aggregate(0, (a, b) => a + b));  // BAD
    }
}
票数 1
EN

Stack Overflow用户

发布于 2013-09-11 23:09:11

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

代码语言:javascript
复制
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<MyClass> {obj1, obj2};
        list1.Should().BeEquivalentTo(obj3, obj4);
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18720582

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档