Tại sao dòng cuối cùng không được phép?
Vì đôi là loại giá trị và đối tượng là loại tham chiếu; hiệp phương sai chỉ hoạt động khi cả hai loại là loại tham chiếu.
Đây có phải vì double là loại giá trị không lấy được từ đối tượng, do đó hiệp phương sai không hoạt động?
No. Số đôi không xuất phát từ đối tượng. Tất cả các loại giá trị xuất phát từ đối tượng.
Bây giờ câu hỏi bạn nên hỏi:
Tại sao hiệp phương sai không hoạt động để chuyển đổi IEnumerable<double>
để IEnumerable<object>
?
Vì ai làm boxing? Một chuyển đổi từ đôi thành đối tượng phải hộp số tăng gấp đôi. Giả sử bạn có cuộc gọi đến IEnumerator<object>.Current
đó là "thực sự" cuộc gọi đến triển khai IEnumerator<double>.Current
. Người gọi mong đợi một đối tượng được trả về. Callee trả về gấp đôi. Mã lệnh thực hiện lệnh đấm bốc ở đâu mà biến số double được trả về bởi IEnumerator<double>.Current
thành một hộp tăng gấp đôi?
Đó là không nơi nào, đó là nơi và đó là lý do tại sao chuyển đổi này là bất hợp pháp. Cuộc gọi đến Current
sẽ đặt một số tám byte lên ngăn xếp đánh giá, và người tiêu dùng sẽ mong đợi một tham chiếu bốn byte đến một hộp kép trên ngăn xếp đánh giá, và vì vậy người tiêu dùng sẽ sụp đổ và chết khủng khiếp với ngăn xếp không đúng và tham chiếu đến bộ nhớ không hợp lệ.
Nếu bạn muốn mã mà hộp để thực hiện sau đó nó phải được viết tại một số điểm, và bạn là người được để viết nó. Cách đơn giản nhất là sử dụng phương pháp Cast<T>
mở rộng:
IEnumerable<object> objects2 = doubleenumerable.Cast<object>();
Bây giờ bạn gọi một phương thức helper có chứa các hướng dẫn đấm bốc có thể chuyển đổi các đôi từ tám byte kép để tham khảo.
CẬP NHẬT: Người nhận xét lưu ý rằng tôi đã trả lời câu hỏi bằng cách giả định sự tồn tại của cơ chế giải quyết vấn đề một cách khó khăn như giải pháp cho câu hỏi ban đầu. Làm thế nào để thực hiện Cast<T>
quản lý để giải quyết vấn đề biết có nên đóng hộp hay không?
Nó hoạt động như bản phác thảo này. Lưu ý rằng các loại tham số là không generic:
public static IEnumerable<T> Cast<T>(this IEnumerable sequence)
{
if (sequence == null) throw ...
if (sequence is IEnumerable<T>)
return sequence as IEnumerable<T>;
return ReallyCast<T>(sequence);
}
private static IEnumerable<T> ReallyCast<T>(IEnumerable sequence)
{
foreach(object item in sequence)
yield return (T)item;
}
Trách nhiệm để xác định liệu các diễn viên từ đối tượng để T là một chuyển đổi unboxing hoặc chuyển đổi tài liệu tham khảo được hoãn lại để thời gian chạy. Jitter biết liệu T là kiểu tham chiếu hay kiểu giá trị. 99% thời gian, tất nhiên nó sẽ là một kiểu tham chiếu.
bản sao có thể có của [Tại sao hiệp phương sai và đối nghịch không hỗ trợ loại giá trị] (http://stackoverflow.com/questions/12454794/why-covariance-and-contravariance-do-not-support-value-type) – nawfal