Có thể được khai báo là contravariant trong T, vì nó chỉ sử dụng T ở vị trí đầu vào (hoặc tương đương, U là một kiểu con của T nên ngụ ý rằng IEquatable <T> là [một kiểu con của] IEquatable <U>). Vì vậy, tại sao nhóm BCL không chú thích nó (cho C# 4.0) với từ khóa 'trong', như chúng đã làm với nhiều giao diện chung khác (giống như IComparable hoàn toàn tương tự)?Tại sao IEquatable T không làm contravariant trong T cho C# 4.0?
Trả lời
Tôi nghĩ rằng đây chủ yếu là vì lý do triết học hơn là giới hạn kỹ thuật – vì nó hoàn toàn có thể đơn giản là chú thích giao diện. IEquatable<T>
là để so sánh các đối tượng cùng loại cho sự bình đẳng chính xác. Một thể hiện của một siêu lớp thường không được coi là tương đương với một thể hiện của một lớp con. Sự bình đẳng theo nghĩa này cũng ngụ ý sự bình đẳng kiểu. Điều này hơi khác một chút so với IComparable<in T>
. Có thể hợp lý để xác định thứ tự sắp xếp tương đối trên các loại khác nhau.
Để báo MSDN page on IEquatable<T>
:
Thuyết minh Implementers:
Thay tham số kiểu của giao diện
IEquatable<T>
với kiểu dữ liệu muốn thực hiện giao diện này.
Câu này chứng minh thêm thực tế là IEquatable<T>
có nghĩa là làm việc giữa các trường hợp của một loại bê tông đơn lẻ.
Cảm ơn; Tôi nghi ngờ điều này là gần với sự thật. Có vẻ như một sự xấu hổ, mặc dù, như U là một subtype của T thực sự có nghĩa là IEquatable T là tương đương với U ... nó chỉ là không IEquatable để U! Nói cách khác, tôi không thấy bất kỳ nhược điểm nào để chú thích giao diện ... –
Tôi thành thật không nhìn thấy bất kỳ * upside * nào để làm cho nó trở nên contravariant. Sẽ không có ý nghĩa khi nói rằng một ví dụ của, 'Xe' là chính xác bằng - hiệu quả giống hệt - một ví dụ của 'Xe hơi'. Chúng có thể tương đương với thứ tự sắp xếp (như với IComparable), nhưng chúng sẽ không bao giờ thực sự "bình đẳng". –
@ Khalid: Xem xét rằng một loại cơ sở lý tưởng không nên biết về các chi tiết của các loại có nguồn gốc của nó, nó không ở một vị trí để quyết định sự bình đẳng của các loại đó. Một lớp dẫn xuất có thể thêm một số thuộc tính, do đó phân tách từ định nghĩa bình đẳng mà lớp cơ sở cung cấp. –
Các loại có thể kế thừa thường không được triển khai IEquatable<T>
. Nếu IEquatable<T>
bao gồm phương thức GetHashCode()
, người ta có thể xác định ngữ nghĩa của IEquatable<T>
để nói rằng các mục nên so sánh bằng nhau khi được kiểm tra là T. Thật không may, thực tế là IEquatable<T>
bị ràng buộc với cùng một mã băm như Object.Equals
có nghĩa là nói chung, IEquatable<T>
phải thực hiện cơ bản cùng ngữ nghĩa như Object.Equals
.
Do đó, nếu một thực hiện IEquatable<BaseClass>
bất cứ điều gì khác hơn gọi Object.Equals
bên trong nó, một lớp có nguồn gốc mà ghi đè Object.Equals
và GetHashCode()
và không tái thực hiện IEquatable<BaseClass>
sẽ kết thúc với một thực hiện vỡ của giao diện đó; việc triển khai IEquatable<BaseClass>
chỉ đơn giản là gọi số Object.Equals
sẽ hoạt động tốt, ngay cả trong trường hợp đó, nhưng sẽ không cung cấp lợi thế thực nào so với lớp không triển khai IEquatable<T>
.
Do các lớp kế thừa không nên triển khai IEquatable<T>
ngay từ đầu, khái niệm hiệp phương sai không liên quan đến việc triển khai thích hợp giao diện.
- 1. Triển khai IEquatable <T> khi T có thể là IEnumerable <T>
- 2. Tại sao T() = T() được phép?
- 3. Tại sao Tùy chọn Scala [T] không trực tiếp dịch sang T trong bytecode?
- 4. Tại sao console.log (đúng, '\ t') in đúng "\t"?
- 5. Tại sao "t instanceof T" không được cho phép trong đó T là tham số kiểu và t là một biến?
- 6. Generics Java - tại sao "mở rộng T" được phép nhưng không "triển khai T"?
- 7. Tại sao IList <T> không có phương thức Chèn lấy IEnumerable <T>?
- 8. Tại sao không có SortedList <T> trong .NET?
- 9. Tại sao EXCEPT tồn tại trong T-SQL?
- 10. Tại sao C# (4.0) không cho phép đồng và contravariance trong các loại lớp chung?
- 11. Tại sao "như T" gặp lỗi nhưng truyền với (T) không nhận được lỗi?
- 12. Tại sao IEnumerable <T> không triển khai Add (T)?
- 13. Tại sao không thể const T * và liên kết với T *?
- 14. Tại sao HashSet <T> không triển khai IReadOnlyCollection <T>?
- 15. Tại sao 'declval' được chỉ định theo 'add_rvalue_reference <T> :: type' và không phải 'T &&'?
- 16. Tại sao giao diện chung không đồng/contravariant theo mặc định?
- 17. Tại sao std :: mảng < T, 0 > không trống?
- 18. Tại sao độ phân giải quá tải của C# không hoạt động giữa Func <T,T> và Hành động <T>?
- 19. Kiểu tham số T đang ẩn kiểu T trong <T> T [] toArray (T [] a) bằng Eclipse
- 20. Tại sao không có lớp ReadOnlyList <T> trong thư viện System.Collections của C#?
- 21. Tại sao mảng <T, N> lại chậm hơn vector <T>?
- 22. Tại sao không có Sắp xếp cho IList <T>?!?! (đã chỉnh sửa)
- 23. Tại sao SynchronizedCollection <T> không khóa trên IEnumerable.GetEnumerator()
- 24. Tại sao không có chuyên môn :: shared_ptr <T[]>?
- 25. Tại sao không BindingList (Of T) có thành viên AddRange?
- 26. C# Tạo mới T()
- 27. Cho chuỗi s, tìm chuỗi ngắn nhất t, sao cho, t^m = s
- 28. Có trường hợp sử dụng cho `newtype T = MkT (T -> T)` không?
- 29. Tại sao Danh sách <T> không an toàn cho chủ đề?
- 30. Tại sao IEnumerable <T> .Max buộc T là IComparable?
Các vấn đề được đề cập trong chuỗi [Nên 'IEquatable', 'IComparable ' được triển khai trên các lớp không phải 'đã được sắp xếp'?] (Http://stackoverflow.com/questions/1868316/should-iequatablet-icomparablet- các lớp được triển khai thực hiện-on-non-sealed) sẽ trở nên tồi tệ hơn nhiều nếu 'IEquatable <>' là contravariant. –