Sự khác biệt giữa giao diện ICompABLE & IEquatable là gì?


Câu trả lời:


188

IEquatable kiểm tra xem hai đối tượng có bằng nhau không.

IComparable áp đặt một thứ tự tổng thể trên các đối tượng được so sánh.

Ví dụ, IEquatablesẽ cho bạn biết rằng 5 không bằng 7. IComparablesẽ cho bạn biết rằng 5 đi trước 7.



10

Ngoài câu trả lời của Greg D:

Bạn có thể triển khai IComparablemà không triển khai IEquatablecho một lớp mà thứ tự một phần có ý nghĩa và nơi bạn chắc chắn muốn người tiêu dùng suy luận rằng chỉ vì CompareTo()trả về 0, điều này không có nghĩa là các đối tượng là bằng nhau (cho bất kỳ điều gì khác ngoài mục đích sắp xếp).


10
Điều đó nghe giống như một trình so sánh trường hợp đặc biệt hơn là một đối tượng triển khai IComparableđúng cách. Bạn có thể đưa ra một ví dụ đầy ý nghĩa nơi CompareTo(…) == 0nào không bao hàm sự bình đẳng? Tôi chắc chắn không thể. Trên thực tế, hợp đồng giao diện (theo MSDN) yêu cầu phảiCompareTo(…) == 0nghĩa là bình đẳng. Nói trắng ra, trong trường hợp như của bạn, hãy sử dụng một Comparatorđối tượng đặc biệt , không nên thực hiện IComparable.
Konrad Rudolph

2
@Konrad - Tôi đã chỉ ra một số cảnh báo - rằng kiểu không triển khai IEquatable (vì vậy rõ ràng, người khởi tạo không muốn bao gồm một bài kiểm tra bình đẳng) và kết quả CompareTo được sử dụng để sắp xếp, không phải để đánh giá sự bình đẳng. Bạn cũng nhận được câu hỏi về sự bình đẳng nào có liên quan (tham chiếu, giá trị, bỏ qua các thuộc tính "tùy ý" - một cuốn sách màu xanh có độ dài 500 trang có thể "bằng" cuốn sách màu đỏ dài 500 trang, vì mục đích của IComp so sánh được)
Damien_The_Un Believer

4
Câu cuối cùng của bạn sai, và đây là lỗi cụ thể mà tôi muốn chỉ ra: IComparablehoàn toàn không phù hợp ở đây. Những gì bạn có là một thứ tự rất đặc biệt chỉ áp dụng trong một tình huống đặc biệt. Đối với những tình huống như vậy, việc triển khai một vị tướng IComparablelà sai lầm. Đây là những gì IComparercó ở đó. Ví dụ, mọi người không thể được sắp xếp một cách có ý nghĩa. Nhưng họ có thể được đặt hàng tùy theo mức lương, cỡ giày, số lượng tàn nhang hoặc trọng lượng của họ. Do đó, chúng tôi sẽ triển khai các IComparers khác nhau cho tất cả các trường hợp này.
Konrad Rudolph

2
@Konrad Rudolph: Còn một thứ gì đó giống như một lớp "SchedisedEvent", được cho là làm "một cái gì đó" vào một thời điểm cụ thể nào đó? Ngữ nghĩa của kiểu sẽ ngụ ý một trật tự ngữ nghĩa tự nhiên rất mạnh dựa trên thời điểm hành động được cho là diễn ra, nhưng người ta có thể dễ dàng có các sự kiện khác nhau xảy ra cùng một lúc. Người ta có thể yêu cầu sử dụng một IComparer được chỉ định thủ công, nhưng tôi sẽ tránh rằng việc có một bộ so sánh được tích hợp trong lớp sẽ thuận tiện hơn.
supercat

4
@supercat Sự tiện lợi là quan trọng, nhưng nó không phải là tất cả. Tính đúng đắn (như trong, tính nhất quán logic) quan trọng hơn và hệ thống kiểu tĩnh là một công cụ quan trọng để xác minh tính nhất quán logic này. Bằng cách vi phạm hợp đồng được lập thành văn bản về giao diện mà bạn thực hiện, bạn đang lật đổ hệ thống loại. Đây không phải là một ý tưởng hay, và tôi sẽ không bao giờ đề xuất nó. Sử dụng công cụ so sánh bên ngoài cho những trường hợp như vậy.
Konrad Rudolph

7

Như đã nêu trên Trang MSDN cho IEquatable :

Giao diện IComp so sánh định nghĩa CompareTophương thức, xác định thứ tự sắp xếp của các thể hiện của kiểu triển khai. Giao diện IEquatable xác định Equalsphương thức, phương thức này xác định sự bình đẳng của các thể hiện của kiểu triển khai.

Equals so với CompareTo


2

IComparable <T> xác định một phương pháp so sánh cụ thể kiểu có thể được sử dụng để sắp xếp hoặc sắp xếp các đối tượng.

IEquatable <T> xác định một phương pháp tổng quát có thể được sử dụng để thực hiện để xác định bình đẳng.


Giả sử bạn có lớp Người

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

Person p1 = new Person() { Name = "Person 1", Age = 34 };
Person p2 = new Person() { Name = "Person 2", Age = 31 };
Person p3 = new Person() { Name = "Person 3", Age = 33 };
Person p4 = new Person() { Name = "Person 4", Age = 26 };

List<Person> people = new List<Person> { p1, p2, p3, p4 };

Để sắp xếp các đối tượng này, bạn có thể sử dụng people.Sort();.

Nhưng điều này sẽ ném ra một ngoại lệ.

nhập mô tả hình ảnh ở đây

Framework không biết cách sắp xếp các đối tượng này. Bạn cần biết cách sắp xếp IComparablegiao diện thực thi .

public class Person : IComparable
{
    public string Name { get; set; }
    public int Age { get; set; }

    public int CompareTo(object obj)
    {
        Person otherPerson = obj as Person;
        if (otherPerson == null)
        {
            throw new ArgumentNullException();
        }
        else
        {
            return Age.CompareTo(otherPerson.Age);
        }
    }
}

Điều này sẽ sắp xếp mảng đúng với Sort()phương thức.


Tiếp theo để so sánh hai đối tượng, bạn có thể sử dụng Equals()phương pháp.

var newPerson = new Person() { Name = "Person 1", Age = 34 };
var newPersonIsPerson1 = newPerson.Equals(p1);

Điều này sẽ trả vềfalseEqualsphương thức không biết cách so sánh hai đối tượng. Do đó, bạn cần phải triển khai IEquatablegiao diện và cho khung làm việc so sánh như thế nào. Mở rộng trên ví dụ trước, nó sẽ giống như thế này.

public class Person : IComparable, IEquatable<Person>
{
    //Some code hidden

    public bool Equals(Person other)
    {
        if (Age == other.Age && Name == other.Name)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
}

1
Cảm ơn vì lời giải thích tuyệt vời này. Câu hỏi: tại sao IEquatablesử dụng chung chung <Person>IComparablekhông sử dụng ?
veuncent
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.