【问题标题】:Declaring an array type声明数组类型
【发布时间】:2013-02-20 12:55:40
【问题描述】:

在讨论另一个关于 SO 的问题时,有人告诉我语法

int[] numbers = new int[10];

优于

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

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

【问题讨论】:

  • 他们做的事情完全不同。
  • 当您在编译时知道类型时,我看不到使用第二种形式的任何好处。
  • 与大多数类不同,Array 提供了 CreateInstance 方法,而不是公共构造函数,以允许后期绑定访问。 - Array.CreateInstance Method
  • @asawyer 他们如何做不同的事情?它们产生确切的效果,除了返回类型可能是..
  • @nawfal 在我看来,不同的返回类型会使某些东西变得不同。

标签: c# arrays


【解决方案1】:

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

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 代码中被优化为直接访问一维数组(stelemldelem)。 GetValue 也是如此。


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

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

【讨论】:

  • 谢谢,这回答了我的疑问,也让我们深入了解 IL 代码。这正是我想要的。接受!
【解决方案2】:

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

第二个的唯一区别是;来自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);

【讨论】:

  • 我不确定我会说返回 int[10] 的表达式和返回 Array 的表达式之间存在“没有区别”。
  • 感谢您的视觉效果。这很有帮助。如果您检查“类型”列,您会发现这两个声明确实不同。
【解决方案3】:

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

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

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

【讨论】:

    【解决方案4】:

    Soner Gönül的回答很不错。您的问题的一个简单原因是

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

    [This answer] 可能会给你带来这个想法,而 [here] 就是一些代码。

    第一种语法什么时候有用,第二种语法什么时候有用?

    例子链接中的方法,

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

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

    大多数时候,如果元素类型在编译时已经知道,最好使用语言提供的语法。

    【讨论】:

      猜你喜欢
      • 2015-02-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多