2010-09-21 76 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>是另一種解決方案。

相關問題