Giao diện IComparable đã lỗi thời / có hại gì không?


11

IComparable chỉ hoạt động một cách

Giả sử bạn có một Employeelớp học. Trong một chế độ xem, bạn muốn hiển thị tất cả được Employeessắp xếp theo tên - trong một chế độ khác, theo địa chỉ. Làm thế nào bạn sẽ đạt được điều đó? Không phải với IComparable, ít nhất là không theo bất kỳ cách thành ngữ nào.

IComparable có logic ở sai chỗ

Giao diện được sử dụng bằng cách gọi .Sort(). Trong chế độ xem hiển thị được Customersắp xếp theo tên, hoàn toàn không có mã để ngụ ý cách sắp xếp nó.
Mặt khác, Customerlớp đang giả định cách nó sẽ được sử dụng - trong trường hợp này, nó sẽ được sử dụng trong một danh sách được sắp xếp theo tên.

IComparable được sử dụng ngầm

So với các lựa chọn thay thế, rất khó để thấy logic so sánh đang được sử dụng ở đâu - hoặc nếu có. Giả sử IDE chuẩn của bạn và bắt đầu từ Customerlớp, tôi sẽ phải

  1. Tìm kiếm tất cả các tham chiếu đến Customer
  2. Tìm những tài liệu tham khảo được sử dụng trong một danh sách
  3. Kiểm tra xem những danh sách đó đã bao giờ .Sort()được gọi trên chúng chưa

Điều gì có thể tồi tệ hơn, nếu bạn loại bỏ một IComparabletriển khai vẫn đang được sử dụng, bạn sẽ không gặp phải lỗi hay cảnh báo nào. Điều duy nhất bạn sẽ nhận được là hành vi sai lầm ở tất cả những nơi quá mơ hồ để bạn nghĩ đến.

Những vấn đề này kết hợp, cộng với yêu cầu thay đổi

Lý do tôi đến để nghĩ về điều này là vì nó đã sai đối với tôi. Tôi đã hạnh phúc sử dụng IComparabletrong ứng dụng của tôi trong 2 năm nay. Bây giờ, các yêu cầu đã thay đổi và điều cần được sắp xếp theo 2 cách khác nhau. Nó đã nhận thấy rằng không có gì vui khi trải qua các bước được mô tả trong phần trước.

Câu hỏi

Những vấn đề này khiến tôi nghĩ IComparablelà kém hơn IComparerhoặc .OrderBy(), đến mức không thấy bất kỳ trường hợp sử dụng hợp lệ nào sẽ không được phục vụ tốt hơn bởi các lựa chọn thay thế.
Có phải luôn luôn tốt hơn để sử dụng IComparerhoặc LINQ, hoặc có những lợi thế / trường hợp sử dụng mà tôi không thấy ở đây?


2
Yêu cầu "sắp xếp hai cách khác nhau" mới của bạn là cá trích đỏ. Để giải quyết nó, tất cả những gì bạn phải làm là chuyển một bộ so sánh khác cho hàm sắp xếp của bạn.
Robert Harvey

@RobertHarvey Sau đó, bạn sẽ không sử dụng IComparablenữa, điều này củng cố quan điểm của tôi.
R. Schmitz

Đừng quên rằng nếu bạn sử dụng các SortedXXXbộ sưu tập, chúng sẽ yêu cầu các yếu tố được lưu trữ phải có IComparablehoặc IComparerđược cung cấp. Cũng lưu ý rằng việc đảo ngược thứ tự tự nhiên với một bộ so sánh là không quan trọng và làm cho nó hoạt động với tất cả IComparablecác đối tượng.
Berin Loritsch

2
Không có vấn đề gì khi có hai giao diện khác nhau. IComparableđược coi là cơ chế so sánh mặc định . IComparerđược sử dụng khi bạn muốn ghi đè cơ chế so sánh mặc định.
Robert Harvey

Câu trả lời:


14

IComparablecó những hạn chế bạn đề cập, đó là chính xác. Nó là một giao diện đã có sẵn trong .NET framework 1.0, trong đó các lựa chọn thay thế chức năng và Linq không có sẵn. Vì vậy, có, người ta có thể xem nó như là một yếu tố khung lỗi thời, chủ yếu được giữ cho khả năng tương thích ngược.

Tuy nhiên, đối với nhiều cấu trúc dữ liệu đơn giản, một cách sắp xếp có lẽ là đủ hoặc tự nhiên. Đối với những trường hợp này, có một vị trí chính tắc để thực hiện mối quan hệ thứ tự vẫn là một cách tốt để giữ mã DRY, thay vì luôn lặp lại cùng một logic trong mỗi lệnh gọi đến OrderBymọi nơi.

Bạn đã "vui vẻ sử dụng IComparable trong ứng dụng của mình được 2 năm rồi", như bạn đã viết, vì vậy nó xuất hiện với tôi nó phục vụ tốt cho bạn trong một thời gian dài. Khi bạn phải xác thực, thay đổi và kiểm tra tất cả các cuộc gọi đến Sort, đó cũng có thể là dấu hiệu bạn đang thực hiện cùng loại logic sắp xếp ở nhiều nơi, đây không phải là lỗi của IComparable. Vì vậy, đây có thể là một dịp để tập trung nhiều logic này vào một nơi, làm cho mã của bạn trở nên KHÔ hơn.


Điểm tốt về các cấu trúc dữ liệu đơn giản. Tuy nhiên, đoạn cuối không có ý nghĩa 100% với tôi. Nếu tôi không sử dụng IComparable, tất cả các mã sắp xếp trước đó sẽ không bị ảnh hưởng trong các chế độ xem tương ứng của họ, trong khi tôi chỉ thêm mã sắp xếp mới cho chế độ xem mới.
R. Schmitz

@ R.Schmitz Sắp xếp từ trước có hoạt động chính xác mà không cần IComparablethực hiện mà bạn đã viết không?
Robert Harvey

3
@ R.Schmitz: Chắc chắn, nhưng bây giờ bạn cam kết luôn cung cấp một bộ so sánh (tất nhiên trừ khi bạn sử dụng OrderBy). Với IComparable, bạn có được một triển khai mặc định miễn phí và đôi khi bạn thậm chí không phải viết triển khai đó.
Robert Harvey

2
@ R.Schmitz: Nhận xét cuối cùng của bạn có tổng hợp điểm độc đáo. Tôi sẽ đi xa hơn một chút. Giả sử bạn có một kiểu số như thế nào BigInteger. Nếu nó không thực hiện các toán tử / giao diện so sánh, bạn thậm chí sẽ tự triển khai một IComparer như thế nào? Bạn cần truy cập vào các cấu trúc dữ liệu nội bộ để thực hiện một cách hiệu quả hoặc hoàn toàn không. Giả sử bạn có một loại như Khách hàng; các tài sản công cộng bạn muốn sắp xếp vào làm có Người đối chiếu. Đối với tôi đó là sự khác biệt: thực hiện IComparable<T>nếu nó không hợp lý để mong đợi người gọi thực hiện một bộ so sánh.
Eric Lippert

1
If I hadn't used IComparable, all the pre-existing sorting code would have been left untouched in their respective views, while I'd only add new sorting code for the new view.Chỉ vì IComparablelà một giải pháp tốt hơn vào thời điểm đó , không có nghĩa đó là giải pháp tốt nhất hiện nay . Nhận xét đầu tiên của bạn ở đây ngụ ý rằng "đó là IComparable hoặc không có gì", điều đó không đúng, vấn đề có thể được giải quyết theo nhiều cách khác nhau. Các ứng dụng có thể tăng kích thước / quy mô và những thứ được sử dụng để trông phù hợp có thể không thể theo kịp nhu cầu ngày càng tăng của ứng dụng.
Flater

1

Tôi đồng ý với tình cảm của bạn về IComparable

Chỉ cần nhìn vào các nhận xét trên Array.Sort()

  • Mỗi phần tử của mảng phải thực hiện IComparablegiao diện để có khả năng so sánh với mọi phần tử khác trong mảng. (hoặc ngoại lệ được ném)
  • Nếu sắp xếp không thành công, kết quả không được xác định.

Chúng tôi có lẽ sẽ không bao giờ là động lực, tuy nhiên! xem xét object.Equals()một phương thức trên mọi đối tượng cho phép bạn so sánh các đối tượng với nhau để xem chúng có "giống nhau" không

Bạn đã có nó rồi, nhưng đã được giao nhiệm vụ thêm Array.Sort()bạn có thể muốn thêmobject.Compare(object)

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.