2010-09-21 46 views
7

我需要比较两个对象,但比较一个命中中的一些属性。 这不是为了排序,而是为了确认是否有任何改变;因为一个是旧保存的实例,第二个是新导入的同一事物的实例检查两个对象实例以查看它们是否相同

我认为最好通过编写自定义比较器来达到这个目的。只是有点困惑至于是否要做IComparerIComparable或什么tbh。

感谢

NAT

+1

这是一个很好的问题。所有的不同比较也让我感到困惑。 – Greg 2010-09-21 13:27:43

回答

8

如果您只有一个关于您班级的平等定义,您并不需要实现任何接口:只需覆盖Equals方法。最佳做法是实现IEquatable<T>并合理地重写GetHashCode(如果不重写散列码,当集合类,LINQ方法等将它用作平等的先决条件时,相等将会行为不当)。这里有一个简单的实现:

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); 
+0

IEquatable Equals与Object中定义的Equals的区别? – Greg 2010-09-21 13:45:04

+0

看起来像它的IEqualityComparer为我在这个例子中,然后,因为我需要检查我的person.ie.managerID,phoneNumber,位置..等数量的属性,如果他们中任何一个已经改变,我需要比较返回false ..除非我失去了一些东西? 但也许我是jsut误解什么gethashcode呢.. – nat 2010-09-21 13:53:03

+0

@nat:是的,确切的。 – Ani 2010-09-21 13:54:21

0

是的,你会需要你的类型,实现IComparable。 Here是如何做到这一点的示例。

+7

您的链接指向此主题。这是一个递归的例子,而不是IComparable;) – Marc 2010-09-21 13:23:09

+1

lol @Marc。非常棒。 – 2010-09-21 13:24:46

+0

也许他的意思是链接:http://support.microsoft.com/kb/320727 – 2010-09-21 13:25:28

0

正如你所提到IComparable接口通常用于排序。

在这种情况下,你会想重载比较运算符:==

因为反向比较也应该是有效的,这意味着你还必须重载=操作符!

当你重载==和! - 你也需要重写Equals和GetHashCode。

一个体面的C#书应解释的细节。

0

实现IComparable接口的替代方法是覆盖Equals和GetHashCode函数。

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方法返回已更改属性的数量。如果比较方法返回0.然后两个Foos是相同的。

正如我所说。这完全是你想要执行我认为的行动。压倒一切的平等运营商也是很好的解决方案。实施IEqualityComparer<T>是另一种解决方案。

相关问题