检查两个对象实例以查看它们是否相同

时间:2010-09-21 13:17:44

标签: c# properties compare equality

我需要比较两个对象,但在一次点击中比较它们的一些属性。 这不是为了排序,而是为了确认是否有任何变化;因为一个是旧保存的实例,第二个是新导入的同一个实例

我认为通过编写自定义比较器可以获得最佳效果。对于是IComparer,还是IComparable,还是tbh,我感到有点困惑。

感谢

NAT

5 个答案:

答案 0 :(得分:9)

如果您的类只有单一的相等定义,则实际上不需要实现任何接口:只需覆盖Equals方法即可。但是,最好的做法是实现IEquatable<T>并明智地覆盖GetHashCode(如果不覆盖哈希代码,当集合类,LINQ方法等将它用作pre时,相等性会出错。 - 平等的条件)。这是一个示例实现:

public class Person : IEquatable<Person>
{
    public string Name { get; set; }
    public int Age { get; set; }

    public override int GetHashCode()
    {
        return (Name == null ? 0 : Name.GetHashCode()) ^ Age;
    }

    public override bool Equals(object obj)
    {
        return Equals(obj as Person);
    }

    public bool Equals(Person other)
    {
        return other != null && other.Name == Name && other.Age == Age;
    }
}

这样你就可以:

Person savedPerson = ...
Person importedPerson = ...

bool hasChanged = !savedPerson.Equals(importedPerson);

另一方面,如果对不同情况确实有很多不同的相等定义,那么最好的办法就是编写不同的IEqualityComparer<T>实现。这是一个示例实现:

public class AgeComparer : IEqualityComparer<Person>
{
    public bool Equals(Person x, Person y)
    {
        return (x == null || y == null) ? x == y : x.Age == y.Age;
    }

    public int GetHashCode(Person obj)
    {
        return obj == null ? 0 : obj.Age;
    }
}  

在这种情况下,检查将如下所示:

Person savedPerson = ...
Person importedPerson = ...
IEqualityComparer<Person> comparer = ...

bool hasChanged = !comparer.Equals(savedPerson, importedPerson);

答案 1 :(得分:0)

是的,你需要你的类型才能实现IComparable。 Here是一个如何做的示例。

答案 2 :(得分:0)

正如您所提到的,IComparable通常用于排序。

在这种情况下,您需要重载比较运算符:==

因为反向比较也应该有效,这意味着你还必须重载!=运算符。

当你重载==和! - 时,你也应该重写Equals和GetHashCode。

一本不错的C#书应该解释一下细节。

答案 3 :(得分:0)

实现IComparable接口的另一种方法是覆盖Equals和GetHashCode函数。

答案 4 :(得分:0)

这是关于你想如何进行比较操作的。您可以通过以下两种方式进行操作:

public void Method()
{
    Foo p1 = new Foo();
    Foo p2 = new Foo();

    p1.CompareTo(p2);
    FooComparer c = new FooComparer();
    c.Compare(p1, p2);
}

class Foo : IComparable
{
    public int CompareTo(object obj)
    {
        throw new NotImplementedException();
    }
}

class FooComparer : IComparer<Foo>
{
    public int Compare(Foo x, Foo y)
    {
        throw new NotImplementedException();
    }
}

我更喜欢使用IComparer作为关注点。 Foo是我的班级,我有一些业务需求。如果我想比较一些Foos,我使用FooComparer。对于您的情况,您可以从Compare方法返回已更改属性的数量。如果Compare方法返回0.则两个Foos相同。

正如我所说。这完全是你想要执行我认为的行动的方式。重写等式运算符也是很好的解决方案。实施IEqualityComparer<T>是另一种解决方案。