Đây là một tính năng đặc biệt khó hiểu của C#. Đây là thỏa thuận.
Trong suốt cuộc thảo luận này, chúng tôi giả định rằng loại phần tử của một mảng là một loại tham chiếu, không phải là một loại giá trị.
C# hỗ trợ hiệp phương sai mảng không an toàn. Điều đó có nghĩa rằng nếu bạn có một mảng của chuỗi, bạn có thể chuyển nó sang một loạt các đối tượng, bởi vì một chuỗi có thể được chuyển đổi sang một đối tượng:
string[] a1 = { "hello", "goodbye" };
object[] a2 = a1; // Legal
Nếu bạn sau đó cố gắng để có được một yếu tố ra khỏi a2, nó hoạt động:
object o3 = a2[0];
đó là quy phạm pháp luật vì a2[0]
thực sự là a1[0]
, mà là một chuỗi, đó là mui trần để phản đối.
Tuy nhiên, nếu bạn cố gắng để ghi đến mảng sau đó bạn sẽ nhận được một lỗi khi chạy:
a2[0] = new object();
này thất bại khi chạy vì a2
là thực sự một mảng các chuỗi, và bạn không thể đặt một chuỗi không vào một chuỗi các chuỗi.
Vì vậy, C# đã bị phá vỡ khủng khiếp; có thể viết một chương trình biên dịch và trông bình thường nhưng đột nhiên đổ vỡ với một kiểu ngoại lệ trong thời gian chạy vì bạn đã cố gắng đặt một đối tượng vào một mảng các đối tượng không thực sự là một mảng các đối tượng.
Tính năng bạn muốn là thậm chí bị vỡ nhiều hơn số và cảm ơn sự tốt lành C# không hỗ trợ tính năng này. Các tính năng mà bạn muốn là:
object[] a4 = { "Hello" };
string[] a5 = a4;
Đó sẽ là mảng không an toàn contravariance. Nó phá vỡ khủng khiếp như thế này:
a4[0] = new Customer(); // Perfectly legal
string s6 = a5[0];
Và bây giờ chúng ta chỉ cần sao chép một khách hàng vào một biến kiểu chuỗi.
Bạn nên tránh bất kỳ loại hiệp phương sai hoặc đối nghịch nào; mâu thuẫn mảng là, như bạn đã phát hiện, không hợp pháp, và hiệp phương sai mảng là làm cho ít thời gian bom trong chương trình của bạn mà đi bất ngờ. Làm cho mảng của bạn đúng loại để bắt đầu.
Bạn đang truyền mảng của mình như thế nào? Nói chung? Bạn cần phải đúc từng phần tử trong mảng của mình. – Msonic
Vâng, anh ấy rõ ràng đang đúc nó như một tổng thể. –
Phương sai mảng tham chiếu là một cách khác; bạn có thể cast cái gì đó ** thực sự là một 'string []' như một 'object []', nhưng để đi theo một cách khác, nó thực sự phải là một 'string []' –