2011-09-04 18 views
7
namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      object[] obj = new object[3]; 
      obj[0] = new object(); 
      obj[1] = "some string"; 
      obj[2] = 10; 

      string[] strings = new string[] { "one", "two", "three" }; 
      obj = strings; //---> No Error here, Why ? 

      int[] ints = new int[] { 1, 2, 3 }; 
      obj = ints; /*-> Compiler error - Cannot implicitly convert type 'int[]' to 'object[]', Why ?*/ 
     } 
    } 
} 

Tôi gặp lỗi trình biên dịch trong khi thực hiện bước như minh họa ở trên. Nhưng, ở bước trên, không có lỗi. Ai đó có thể giải thích cho tôi hành vi này? Tôi đang sử dụng VS 2010.C# - Lỗi trình biên dịch - trong khi gán int [] cho đối tượng []

EDIT - Để hoàn tất, một lần nữa, thao tác này sẽ không biên dịch - Hỗ trợ khác biệt trong .NET 4.0 đã được dọn dẹp ngay bây giờ. Người ta có thể sử dụng từ khóa mới trongra với thông số loại chung.

List<object> objectList = new List<object>(); 
    List<string> stringList = new List<string>(); 
    objectList = stringList; 
+2

Bạn có hiểu sự khác nhau giữa loại giá trị và loại tham chiếu? – Oded

Trả lời

6

Chỉ mảng của các loại tài liệu tham khảo (như String) có thể chuyển nhượng cho mảng của các loại tài liệu tham khảo khác (như Object). Vì int là một loại giá trị, mảng của nó có thể không được gán cho các mảng khác.

Để cụ thể hơn, điều này được gọi là array covariance. Nó chỉ hoạt động khi các mẫu bit được lưu trữ trong mảng tương thích với kiểu đích. Ví dụ, các bit trong một String[] là tất cả các tham chiếu đến chuỗi và có thể được sao chép một cách an toàn vào các vị trí bộ nhớ lưu trữ các tham chiếu đến các đối tượng. Tuy nhiên, một mảng các loại giá trị lưu trữ dữ liệu thực tế của các phần tử (trái ngược với chỉ các tham chiếu đến chúng). Điều này có nghĩa là số int[] lưu trữ các số nguyên 32 bit thực trong các phần tử của mảng. Vì một số nguyên 32 bit không thể được sao chép một cách an toàn vào một vị trí bộ nhớ lưu trữ một tham chiếu đến một đối tượng hoặc bất kỳ loại nào khác, bạn không thể gán một mảng cho một mảng của bất kỳ loại nào khác.

Lưu ý rằng về mặt kỹ thuật, các bit của int có thể được sao chép an toàn vào vị trí bộ nhớ lưu trữ uint (và ngược lại). Điều này có nghĩa là bạn sẽ có thể làm điều gì đó như int[] x = new uint[10]. Điều này không thực sự hiệp phương sai và C# không cho phép nó. Tuy nhiên, nó là hợp pháp trong CLR và bạn có thể thuyết phục C# để cho phép bạn làm điều đó nếu bạn muốn.

+0

Nhưng mọi thứ cuối cùng là system.object –

+0

Cảm ơn Gabe. Mảng hiệp phương sai là chìa khóa! –

1

những gì tôi thấy là một mảng các loại tham chiếu có thể được chỉ định cho một mảng các loại tham chiếu khác trong khi một mảng các loại giá trị không thể. Hợp lý với tôi

2

stringobject là cả hai loại tham chiếu. Đó là, một biến của những loại thực sự lưu trữ một con trỏ đến một nơi khác trong bộ nhớ. int là một loại giá trị. Tức là, dữ liệu được lưu trữ trực tiếp nơi biến được khai báo.

Điều này có nghĩa là một mảng các loại tham chiếu về cơ bản khác với một mảng các loại giá trị. Một mảng các kiểu tham chiếu được lưu trữ như là một mảng các con trỏ. Bởi vì con trỏ có cùng kích thước, điều này có nghĩa là để giải thích lại string[] là một phương tiện giả object[] có nghĩa là điều chỉnh việc kiểm tra kiểu khi thực hiện truy cập các mục trong mảng (nói gần).

Tuy nhiên, trong một int[], các giá trị được lưu trữ trực tiếp trong mảng; các giá trị int được nối với nhau. Không có con trỏ nào có liên quan. Điều này có nghĩa là để diễn giải lại một số int[] dưới dạng object[] yêu cầu phải có mọi giá trị được lưu trữ trong mảng vào đối tượng. Do đó, tại sao bạn không thể làm điều đó bằng cách sử dụng một diễn viên hoặc nhiệm vụ đơn giản - đó là một hoạt động O (n) tạo ra một mảng mới. Thay vào đó, bạn có thể sử dụng Array.Copy để giao dịch với tất cả quyền anh dành cho bạn.

0

Nếu bạn có cài đặt Visual Studio, bạn sẽ tìm thấy tệp Ngôn ngữ Speicifcation C# dưới dạng tệp doc ở đâu đó trong VC#. Chương 125 giao dịch với hiệp phương sai và có nó nói

Đối với bất kỳ hai tài liệu tham khảo-loại A và B, nếu một tài liệu tham khảo ngầm chuyển đổi (§6.1.6) hoặc chuyển đổi tài liệu tham khảo rõ ràng (§6.2.4) tồn tại từ A đến B, thì chuyển đổi tham chiếu tương tự cũng tồn tại từ loại mảng A [R] thành kiểu mảng B [R], trong đó R là bất kỳ số nào được đưa ra thứ hạng-specifier (nhưng giống nhau cho cả hai loại mảng). Mối quan hệ này được gọi là hiệp phương sai mảng.

Điều này có thể không trả lời được câu hỏi của bạn, nhưng đó là một quyết định có chủ ý trong thông số để thực hiện theo cách đó.

1

Tại sao tính năng này không hoạt động được nêu trong nhiều câu trả lời ở đây, vì vậy tôi sẽ không cố gắng sao chép-dán những gì họ đã nói.

Nếu bạn hoặc ai đó thực sự muốn làm điều đó (chuyển đổi int[] để object[]) đối với một số lý do, bạn có thể sử dụng LINQ như vậy:

int[] ints = new int[] { 1, 2, 3 }; 
object[] obj_ints = (from i in ints select i).Cast<object>().ToArray(); 

;)

+0

Có thể có nhiều cách giải quyết. Vui lòng xem câu trả lời từ 'Gabe' bên dưới –

+1

Tại sao không chỉ sử dụng 'Array.Copy'? http://msdn.microsoft.com/en-us/library/system.array.copy.aspx – Gabe

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