在 Stack Overflow 讨论另一个问题时,有人告诉我关于语法
int[] numbers = new int[10];
比...更好
Array numbers = Array.CreateInstance(typeof(int), 10);
我的问题是,第一种语法在什么情况下有用,第二种语法在什么情况下有用?为什么?
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
/'something
')。所以:int num = (int)array2.GetValue(1); // You have to cast the return value to int from object
array[5] = 1;
array2.SetValue(5, 1);
第一种方法在IL代码中被优化为对单维数组(stelem
和ldelem
)的直接访问。同样适用于GetValue
。
我使用“单维数组”这个术语的原因:
在.NET中有两种“类型”的数组: 单维数组和“复杂”数组(它们可以是多维的,或者第一个元素不在0索引处,或这两种情况都有)。第二组要慢得多。stelem
和ldelem
仅适用于单维数组。对于多维/特殊数组,会使用“隐藏的”方法来访问它们(C#编译器会更改get和set,以便调用这些方法)(它们类似于Array
类的GetValue
/SetValue
,例如https://dev59.com/dnRB5IYBdhLWcg3wiHll#597729)。
null
,值类型元素初始化为 zero
。
与大多数类不同,数组提供了CreateInstance方法而不是公共构造函数,以允许进行后期绑定访问。
正如Stefano Altieri 提到的那样,第一种语法需要在编译时指定数组大小,但第二种需要在运行时指定大小。例如,您可以成功构建这些代码;
int[] numbers1 = new int[10];
Array numbers2 = Array.CreateInstance(typeof(int), -1);
但你无法建造这些;
int[] numbers1 = new int[];
Array numbers2 = Array.CreateInstance(typeof(int), -1);
int[10]
和返回 Array
的表达式之间“没有区别”。 - asawyerType myType = SelectTheBestType();
var numbers = Array.CreateInstance(myType, 10);
Soner Gönül的回答非常好。简单来说,如果将数组作为对象或接口传递,则编译时元素类型未知。
[这个答案]可能会给您带来一些想法,[这里]有一些示例代码。
第一个语法何时有用,第二个语法何时有用?
链接中的方法,
static IList CreateArray<T>(this T source);
因为我不能假设source
必须是一个数组,但它仍然可能是一个数组,所以通用类型参数是T
而不是T[]
。因此我只能在方法内部使用Array.CreateInstance
。
大多数情况下,如果元素类型在编译时已知,则最好使用语言提供的语法。
Cat
与Cat
是否完全不同? - nawfal