声明一个数组类型

时间:2013-02-20 12:55:41

标签: c# arrays

在讨论关于SO的另一个问题时,我被告知语法

int[] numbers = new int[10];

优于

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

我的问题是,第一种语法何时有用,何时第二种语法有用?为什么?

4 个答案:

答案 0 :(得分:6)

这会“直接”创建一个强类型的单维数组:

int[] array = new int[10];

在幕后,它使用IL命令newarr

这个更类似于使用反射来创建数组(类型可以在运行时决定)

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

最终创建的数组是相同的,但使用Array.CreateInstance时创建它的速度要慢得多。请注意,使用Array.CreateInstance,您可以动态选择数组的类型(与通过反射相同的方式,您可以创建在运行时给定类型的类型的实例),例如:

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

另一个重大区别:“基础”Array类是弱类型的(因此其方法使用object参数,而不是int / string'/ {{1 }})。所以:

something

使用

的另一个原因
int num = (int)array2.GetValue(1); // You have to cast the return value to int from object

而不是

array[5] = 1;

是第一种方法在IL代码中被优化为对一维数组(array2.SetValue(5, 1); stelem)的直接访问。 ldelem也是如此。


我使用术语“单维数组”的原因是:

在.NET中有两种“类型”的数组:单维数组和“复杂”数组(它们可以是多维的,或者第一个元素不在0索引处,或两者都有)。第二组要慢得多。 GetValuestelem仅适用于单维数组。对于多维/特殊数组,使用“隐藏”方法来访问它们(C#编译器更改get和set以便调用这些方法)(它们类似于ldelem / GetValue { {1}}类,例如参见https://stackoverflow.com/a/597729/613130

答案 1 :(得分:5)

在编译时,看起来它们之间没有太大的区别。与数组一样, Array.CreateInstance 方法也会将引用类型元素初始化为null。 value-type元素初始化为zero

enter image description here

唯一不同的是第二个;来自 MSDN ;

  

与大多数类不同,Array提供CreateInstance方法   公共构造函数,允许后期绑定访问。

另外,作为Stefano Altieri mentioned,第一种语法需要编译时中的数组大小,但第二种语法需要运行时中的大小。例如,您可以成功构建这些代码;

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

但你无法建立这些;

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

答案 2 :(得分:4)

您编写的样本是等效的。关键是要使用第一种语法(new int [size]),你需要在编译时知道数组类型。

第二种语法允许您在运行时决定数组项的类型。这更强大,但你总是不需要这种力量。即

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

答案 3 :(得分:2)

Soner Gönül的答案非常好。问题的一个简单原因是

如果数组作为对象或接口传递,则元素类型在编译时是未知的。

[This answer]可能会为您提供这个想法,[here]就是一些代码。

  

第一个语法何时有用,何时第二个语法有用?

示例链接中的方法

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

泛型类型参数是T而不是T[]因为我不能认为source 必然是一个数组,但它仍然可能即可。因此,我只能在方法中使用Array.CreateInstance

大多数情况下,如果在编译时已知元素类型,则最好使用该语言提供的语法。