Nói tóm lại: mảng hiệp phương sai chỉ hoạt động khi cả hai mảng đều thuộc loại tham chiếu (class
).
Để hiểu điều này, bạn phải hiểu bố cục bộ nhớ của các loại mảng khác nhau. Trong C# chúng ta có mảng giá trị (int[]
, float[]
, DateTime[]
, bất kỳ người dùng định nghĩa struct[]
) trong đó mỗi điều được lưu trữ liên tục bên trong mảng, và tham khảo các mảng (object[]
, string[]
, bất kỳ người dùng định nghĩa class[]
, interface[]
, hoặc delegate[]
), nơi tài liệu tham khảo được lưu trữ tuần tự bên trong mảng và các đối tượng được lưu trữ bên ngoài mảng bất cứ nơi nào chúng phù hợp với bộ nhớ.
Khi bạn yêu cầu mà công việc phương pháp trên bất kỳ T
(không có : class
hạn chế), bạn cho phép một trong hai loại mảng, nhưng trình biên dịch biết một thực tế là bất kỳ int[]
(hoặc bất kỳ mảng giá trị khác) không phải là bằng cách nào đó kỳ diệu trở thành IFoo[]
hợp lệ (hoặc bất kỳ mảng tham chiếu nào khác) và cấm chuyển đổi. Điều này xảy ra ngay cả khi cấu trúc của bạn triển khai IFoo
vì không có lý do nào khác hơn IFoo[]
là một mảng tham chiếu và một T[]
sẽ là một mảng giá trị.
Tuy nhiên, khi bạn xác định rằng T
là một loại tài liệu tham khảo (ví dụ: khai báo class
), bây giờ có thể rằng T[]
là một giá trị IFoo[]
vì họ đều là những mảng tham khảo. Vì vậy, trình biên dịch cho phép mã sử dụng các quy tắc hiệp phương sai (mà bạn có thể sử dụng T[]
trong đó IFoo[]
là bắt buộc vì T
là một loại phụ của IFoo
).
Nguồn
2015-12-11 19:56:40
Một hệ thống kiểu tốt nên có loại so khớp có thể được sử dụng làm mảng có các mục có thể được đọc, hoán đổi hoặc sao chép trong mảng. Các loại mảng trong .NET và Java có thể được sử dụng một cách an toàn theo kiểu biến đổi như các kiểu như vậy và có thể được sử dụng một cách an toàn theo kiểu không biến đổi như các bộ sưu tập có thể ghi tự do. Có lẽ sẽ tốt hơn nếu có nhiều loại tham chiếu đến mảng, với những khả năng được quảng cáo khác nhau, nhưng IMHO những người chỉ đơn giản nói các mảng biến đổi là một "sai lầm" đã không thực sự tìm ra chi phí của các giải pháp thay thế. – supercat