8

While discussing another question on SO, I was told that the syntax

int[] numbers = new int[10];

Is better than

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

My question is, when is the first syntax useful and when is the second syntax useful? And why?

TheSilverBullet
  • 605
  • 7
  • 21
  • They do completely different things. – asawyer Feb 20 '13 at 12:56
  • 7
    When you know the type at compile time, I can't see *any* benefit to using the second form. – Jon Skeet Feb 20 '13 at 12:58
  • 1
    Unlike most classes, Array provides the CreateInstance method, instead of public constructors, to allow for **late bound access**. - [Array.CreateInstance Method](http://msdn.microsoft.com/en-us/library/zb3cfh7k.aspx) – Habib Feb 20 '13 at 13:00
  • @asawyer how do they do different things? They produce the exact effect, except for the return type may be.. – nawfal Apr 25 '13 at 19:11
  • @nawfal Seems to me that a different return type would qualify something as different. – asawyer Apr 25 '13 at 19:39
  • @asawyer but are they really different? Run a GetType() on both of them and they are just the same. Its only a question how it is *typed*. And its only a matter of casting to its original type. Even if still they are different, they **are not completely different**. Is `Cat` **completely** different from `Cat` in the guise of `Mammal`? – nawfal Apr 25 '13 at 19:59
  • @nawfal For compile time static analysis, yes it they are different. – asawyer Apr 25 '13 at 20:09
  • @asawyer honestly my first comment was regarding the "completely" part, which makes OP's question look like silly. Nevertheless you chipped in with your appropriate justification ;) If you comment the same under questions like *when to use `IList` over `List`* etc I wont complain :) – nawfal Apr 25 '13 at 20:12

4 Answers4

8

This creates a strongly typed monodimensional array "directly":

int[] array = new int[10];

Under the hood it uses the IL command newarr.

This one is more similar to using reflection to create an array (the type can be decided at runtime)

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

The array created in the end is the same but the speed of creating it is much slower when using Array.CreateInstance. Note that with Array.CreateInstance you can dynamically select the type of the array (in the same way that through reflection you can create an instance of a type given the type at runtime), for example:

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

Another big difference: the "base" Array class is weakly typed (so its methods use object parameters, instead of int/string'/something). So:

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

Another reason to use

array[5] = 1;

instead of

array2.SetValue(5, 1);

is that the first method is optimized in the IL code as a direct access to a monodimensional array (stelem and ldelem). The same is true for GetValue.


The reason I'm using the term "monodimensional array":

In .NET there are two "types" of arrays: the monodimensional arrays and the "complex" arrays (they can be multidimensional, or with the first element not at the 0 index, or both). The second group is much slower. The stelem and ldelem work only with monodimensional arrays. For multidimensional/special arrays "hidden" methods are used to access them (the C# compiler changes the get and set so that these methods are called) (they are similar to the GetValue/SetValue of the Array class, see for example https://stackoverflow.com/a/597729/613130 )

Community
  • 1
  • 1
xanatos
  • 109,618
  • 12
  • 197
  • 280
5

On compile time, looks like there is no big difference between them. Just like arrays, Array.CreateInstance method also make reference-type elements are initialized to null. value-type elements are initialized to zero.

enter image description here

Only difference for the second one is; from MSDN;

Unlike most classes, Array provides the CreateInstance method, instead of public constructors, to allow for late bound access.

Also as Stefano Altieri mentioned, first syntax requires array size in compile time, but the second one need the size in run-time. For example, you can build these codes successfully;

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

But you can't build these;

int[] numbers1 = new int[];
Array numbers2 = Array.CreateInstance(typeof(int), -1);
Community
  • 1
  • 1
Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
  • 1
    I'm not sure I'd say that there is "No difference" between an an expression that returns `int[10]` and an expression that returns `Array`. – asawyer Feb 20 '13 at 13:07
  • 1
    Thanks for the visual. It is helpful. If you do check the "Type" column, you will see that the two declarations are indeed different. – TheSilverBullet Feb 21 '13 at 12:45
4

The samples you wrote are equivalent. The point is that to use the first syntax (new int[size]) you need to know the array type at compile time.

The second syntax allow you to decide at runtime the type of the array items. This is far more powerful, but you just don't need this power always. I.e.

Type myType = SelectTheBestType();
var numbers = Array.CreateInstance(myType, 10);
Stefano Altieri
  • 4,550
  • 1
  • 24
  • 41
2

Soner Gönül's answer is pretty good. A simple reason of your question is

If an array is passed as object or interface, the element type is unknown at compile time.

[This answer] might bring you the idea, and [here] is some code for example.

when is the first syntax useful and when is the second syntax useful?

The method in the link of example,

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

the generic type parameter is T rather than T[] because of I cannot suppose that source necessarily been an array, but it still possibly. Thus I can only use Array.CreateInstance inside the method.

Most of time, if the element type is already known at compile time, it's better to use the syntax provided by the language.

Community
  • 1
  • 1
Ken Kin
  • 4,503
  • 3
  • 38
  • 76