Phương sai sẽ chỉ được hỗ trợ một cách an toàn - trên thực tế, bằng cách sử dụng các khả năng mà CLR đã có. Vì vậy, các ví dụ tôi đưa ra trong cuốn sách về việc cố gắng sử dụng a List<Banana>
như một List<Fruit>
(hoặc bất cứ điều gì đó là) vẫn sẽ không hoạt động - nhưng một số trường hợp khác sẽ làm được.
Thứ nhất, nó sẽ chỉ được hỗ trợ cho giao diện và đại biểu.
Thứ hai, nó yêu cầu tác giả của giao diện / đại biểu trang trí các tham số kiểu như in
(đối với tương phản) hoặc out
(đối với hiệp phương sai). Ví dụ rõ ràng nhất là IEnumerable<T>
chỉ cho phép bạn lấy các giá trị "ra khỏi" nó - nó không cho phép bạn thêm các giá trị mới. Điều đó sẽ trở thành IEnumerable<out T>
. Điều đó hoàn toàn không ảnh hưởng đến an toàn kiểu, nhưng cho phép bạn trả về một IEnumerable<string>
từ một phương thức được khai báo để trả về IEnumerable<object>
chẳng hạn.
Sự tương phản khó đưa ra các ví dụ cụ thể để sử dụng các giao diện, nhưng lại dễ dàng với một đại biểu. Hãy xem xét Action<T>
- điều đó chỉ đại diện cho một phương thức nhận một T
tham số. Sẽ thật tuyệt nếu có thể chuyển đổi liền mạch bằng cách sử dụng một Action<object>
như một Action<string>
- bất kỳ phương thức nào có object
tham số sẽ ổn khi nó được trình bày với một string
thay thế. Tất nhiên, C # 2 đã có hiệp phương sai và phương sai của các đại biểu ở một mức độ nào đó, nhưng thông qua một chuyển đổi thực tế từ loại đại biểu này sang loại đại biểu khác (tạo một trường hợp mới) - xem ví dụ P141-144. C # 4 sẽ làm cho điều này chung chung hơn và (tôi tin rằng) sẽ tránh tạo một phiên bản mới cho chuyển đổi. (Thay vào đó, nó sẽ là một chuyển đổi tham chiếu.)
Hy vọng điều này sẽ làm sáng tỏ một chút - vui lòng cho tôi biết nếu nó không hợp lý!