2010-09-21 39 views
7

tôi cần so sánh hai đối tượng nhưng so sánh một số thuộc tính của chúng trong một lần truy cập. đây không phải để sắp xếp, mà thay vào đó để xác nhận xem có điều gì đã thay đổi hay không; vì một là trường hợp đã lưu cũ và phiên bản thứ hai là một phiên bản mới được nhập cùng một thứkiểm tra hai trường hợp đối tượng để xem chúng có giống nhau không

tôi giả sử điều này được phục vụ tốt nhất bằng cách viết trình so sánh tùy chỉnh. chỉ là một chút bối rối về việc có nên thực hiện IComparer hoặc IComparable hoặc tbh hay không.

nhờ

nat

+1

Đó là một câu hỏi hay. Tất cả sự so sánh khác nhau cũng làm tôi bối rối. – Greg

Trả lời

8

Nếu bạn chỉ có một định nghĩa bình đẳng duy nhất cho lớp học của mình, bạn không thực sự cần triển khai bất kỳ giao diện nào: chỉ cần ghi đè phương thức Equals. Mặc dù vậy, thực hành tốt nhất là triển khai IEquatable<T> và ghi đè lên GetHashCode một cách hợp lý (nếu bạn không ghi đè mã băm, bình đẳng sẽ hoạt động sai khi các lớp thu thập, phương pháp LINQ, vv sử dụng nó như là điều kiện tiên quyết cho sự bình đẳng). Dưới đây là một việc thực hiện mẫu:

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; 
    } 
} 

Điều này sẽ cho phép bạn làm:

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

bool hasChanged = !savedPerson.Equals(importedPerson); 

Nếu, mặt khác, bạn có rất nhiều định nghĩa khác nhau về sự bình đẳng cho hoàn cảnh khác nhau, bạn đặt cược tốt nhất là viết lên các triển khai khác nhau IEqualityComparer<T>. Dưới đây là một việc thực hiện mẫu:

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; 
    } 
} 

Trong trường hợp này, việc kiểm tra sẽ trông giống như:

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

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

Làm thế nào để IEquatable Equals khác với Equals được xác định trên Object? – Greg

+0

trông giống như IEqualityComparer của tôi trong trường hợp này sau đó, vì tôi cần kiểm tra một số thuộc tính của person.ie.managerID, phoneNumber, vị trí ..vv và nếu có bất kỳ thay đổi nào, tôi cần so sánh để trả về false .. trừ khi tôi đang thiếu cái gì đó? nhưng có lẽ tôi đang hiểu nhầm về những gì gethashcode làm .. – nat

+0

@nat: Vâng, chính xác. – Ani

0

Có bạn sẽ cần phải loại của bạn để thực hiện IComparable. Here là mẫu về cách thực hiện.

+7

Điểm liên kết của bạn quay lại chủ đề này. Đó là ví dụ về đệ quy, không phải IComparable;) – Marc

+1

lol @Marc. Cú bắt tuyệt vời. –

+0

Có lẽ anh ta muốn liên kết: http://support.microsoft.com/kb/320727 –

0

Như các bạn đã ám chỉ IComparable thường được sử dụng để phân loại.

Trong trường hợp này bạn sẽ muốn quá tải toán tử so sánh: ==

Bởi vì sự so sánh ngược lại cũng nên có giá trị, điều này có nghĩa bạn cũng phải quá tải toán tử =!.

Khi bạn quá tải == và! - bạn cũng được dự kiến ​​sẽ ghi đè Bằng và GetHashCode.

Sách C# phong nha nên giải thích chi tiết.

0

Một giải pháp thay thế để triển khai giao diện IComparable sẽ là ghi đè hàm Equals và GetHashCode.

0

Đó là về cách bạn muốn thực hiện thao tác so sánh. Bạn có thể thực hiện thao tác theo cả hai cách:

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(); 
    } 
} 

Tôi thích sử dụng IComparer hơn khi phân tách các mối quan ngại. Foo là lớp học của tôi, tôi có một số nhu cầu của busines. Nếu tôi muốn so sánh một số Foos, tôi sử dụng FooComparer. Đối với trường hợp của bạn, bạn có thể trả lại số lượng các thuộc tính đã thay đổi từ phương thức So sánh. Nếu so sánh phương thức trả về 0. Sau đó, hai Foos giống nhau.

Như tôi đã nói. Đó hoàn toàn là cách bạn muốn thực hiện hành động mà tôi nghĩ. Overriding Equality Operators cũng là giải pháp tốt. Việc triển khai IEqualityComparer<T> là một giải pháp khác.

Các vấn đề liên quan