2013-02-20 36 views
7

Trong khi thảo luận một câu hỏi về SO, tôi được cho biết rằng cú phápTuyên bố một loại mảng

int[] numbers = new int[10]; 

là tốt hơn so với

Array numbers = Array.CreateInstance(typeof(int), 10); 

Câu hỏi của tôi là, khi là cú pháp đầu tiên hữu ích và khi nào là cú pháp thứ hai hữu ích? Và tại sao?

+0

Họ làm những việc hoàn toàn khác nhau. – asawyer

+6

Khi bạn biết loại tại thời gian biên dịch, tôi không thể thấy * bất kỳ * lợi ích nào khi sử dụng biểu mẫu thứ hai. –

+1

Không giống như hầu hết các lớp, Array cung cấp phương thức CreateInstance, thay vì các hàm tạo công khai, để cho phép ** truy cập bị ràng buộc trễ **. - [Array.CreateInstance Method] (http://msdn.microsoft.com/en-us/library/zb3cfh7k.aspx) – Habib

Trả lời

6

này tạo ra một mảng monodimensional mạnh mẽ gõ "trực tiếp":

int[] array = new int[10]; 

Dưới mui xe nó sử dụng lệnh IL newarr.

Cái này là tương tự như sử dụng phản ánh để tạo ra một mảng (loại có thể được quyết định trong thời gian chạy)

int[] array2 = (int[])Array.CreateInstance(typeof(int), 10); 

Mảng tạo cuối cùng là như nhau nhưng tốc độ của việc tạo ra nó được chậm hơn khi sử dụng Array.CreateInstance.Lưu ý rằng với Array.CreateInstance bạn có thể chủ động chọn kiểu mảng (trong cùng một cách mà thông qua phản ánh bạn có thể tạo một thể hiện của một loại nhất định các loại trong thời gian chạy), ví dụ:

Type type = someCondition ? typeof(int) : typeof(string); 
Array array2 = Array.CreateInstance(type, 10); 

Một sự khác biệt lớn: lớp "cơ sở" Array được nhập sai (do đó phương pháp của nó sử dụng thông số object, thay vì int/string '/ something). Vì vậy:

int num = (int)array2.GetValue(1); // You have to cast the return value to int from object 

lý do khác để sử dụng

array[5] = 1; 

thay vì

array2.SetValue(5, 1); 

được rằng phương pháp đầu tiên được tối ưu hóa trong mã IL là truy cập trực tiếp tới một monodimensional mảng (stelemldelem). Điều này cũng đúng cho GetValue.


Lý do tôi đang sử dụng thuật ngữ "monodimensional mảng":

Trong NET có hai "loại" của mảng: mảng monodimensional và các mảng "phức tạp" (họ có thể đa chiều , hoặc với phần tử đầu tiên không có chỉ số 0, hoặc cả hai). Nhóm thứ hai chậm hơn nhiều. Các stelemldelem chỉ hoạt động với các mảng một chiều. Đối với đa chiều mảng/đặc biệt phương pháp "ẩn" được sử dụng để truy cập chúng (C# biên dịch làm thay đổi get và thiết lập để cho các phương pháp này được gọi là) (họ cũng tương tự như các GetValue/SetValue của lớp Array, xem ví dụ https://stackoverflow.com/a/597729/613130)

+0

Cảm ơn, điều này trả lời truy vấn của tôi và cũng cung cấp thông tin chi tiết về mã IL. Đây chính xác là những gì tôi đang tìm kiếm. Đã chấp nhận! – TheSilverBullet

5

Khi biên dịch, có vẻ như không có sự khác biệt lớn giữa chúng. Cũng giống như mảng, phương pháp Array.CreateInstance cũng làm cho các yếu tố loại tham chiếu được khởi tạo thành null. các phần tử kiểu giá trị được khởi tạo thành zero.

enter image description here

Chỉ khác biệt cho một thứ hai là; từ MSDN;

Không giống như hầu hết các lớp, Array cung cấp phương thức CreateInstance, thay vào đó là của các nhà xây dựng công cộng, để cho phép truy cập bị ràng buộc trễ.

Cũng như Stefano Altieri mentioned, cú pháp đầu tiên yêu cầu kích thước mảng trong thời gian biên dịch, nhưng điều thứ hai cần kích thước trong thời gian chạy. Ví dụ, bạn có thể xây dựng các mã này thành công;

int[] numbers1 = new int[10]; 
Array numbers2 = Array.CreateInstance(typeof(int), -1); 

Nhưng bạn không thể tạo chúng;

int[] numbers1 = new int[]; 
Array numbers2 = Array.CreateInstance(typeof(int), -1); 
+1

Tôi không chắc mình muốn nói rằng có " Không có sự khác biệt giữa một biểu thức trả về 'int [10]' và một biểu thức trả về 'Mảng'. – asawyer

+1

Được thăng hạng. Một thử nghiệm thực sự là tốt. –

+1

Cảm ơn hình ảnh. Nó rất hữu dụng. Nếu bạn kiểm tra cột "Loại", bạn sẽ thấy rằng hai khai báo thực sự khác nhau. – TheSilverBullet

4

Mẫu bạn đã viết tương đương. Vấn đề là sử dụng cú pháp đầu tiên (int [size] mới) bạn cần biết kiểu mảng tại thời gian biên dịch.

Cú pháp thứ hai cho phép bạn quyết định khi chạy loại mục mảng. Điều này mạnh hơn rất nhiều, nhưng bạn không cần sức mạnh này luôn. I E.

Type myType = SelectTheBestType(); 
var numbers = Array.CreateInstance(myType, 10); 
2

Câu hỏi của Soner Gönül là khá tốt. Một lý do đơn giản cho câu hỏi của bạn là

Nếu một mảng được truyền dưới dạng đối tượng hoặc giao diện, loại phần tử không xác định tại thời gian biên dịch.

] [This answer] có thể mang lại cho bạn ý tưởng và [here] là một số mã ví dụ.

khi nào cú pháp đầu tiên hữu ích và khi nào cú pháp thứ hai hữu ích?

Phương pháp trong liên kết của các ví dụ,

static IList CreateArray<T>(this T source); 

tham số kiểu chung chung là T hơn T[] vì tôi không thể giả sử rằng sourcethiết được một mảng, nhưng nó vẫn thể . Vì vậy tôi chỉ có thể sử dụng Array.CreateInstance bên trong phương thức.

Hầu hết thời gian, nếu loại phần tử đã được biết tại thời gian biên dịch, tốt hơn là sử dụng cú pháp do ngôn ngữ cung cấp.