2010-07-20 31 views
16

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?

+0

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. –

Trả lời

13

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ẻ.

+0

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 ... –

+0

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". –

+1

@ 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. –

1

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.EqualsGetHashCode() 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.

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