Direct array initialization with a constant value

Whenever you allocate a new array in C# with

new T[length]

the array entries are set to the default of T. That is null for the case that T is a reference type or the result of the default constructor of T, if T is a value type.

In my case i want to initialize an Int32 array with the value -1:

var myArray = new int[100];
for (int i=0; i<myArray.Length; i++) { myArray[i] = -1; }

So after the memory is reserved for the array, the CLR loops over the newly allocated memory and sets all entries to default(int) = 0. After that, my code sets all entries to -1.

That makes the initialization redundant. Does the JIT detect this and neglects the initialization to 0 and if not, is there a way to directly initialize a portion of memory with a custom value?

Referring to C# Array initialization - with non-default value , using Enumerable.Repeat(value, length).ToArray() is no option, because Enumerable.ToArray allocates a new array and copies the values to it afterwards.


Solution 1:

Similar to Dan's answer but without the need of using collections:

int[] myArray = Enumerable.Repeat(-1, 100).ToArray();

Solution 2:

It's not redundant.

Suppose an exception is thrown during your initialization loop. If the CLR hasn't cleared the memory first, you might be able to "see" the original uninitialized memory, which is a very bad idea, particularly from a security standpoint. That's why the CLR guarantees that any newly allocated memory is wiped to a 0 bit pattern.

The same argument holds for fields in an object, by the way.

I suppose in both cases the CLR could check that you're not going to make the array visible elsewhere before finishing initialization, but it's a complicated check to avoid a pretty simple "wipe this area of memory".

Solution 3:

If you buy into Arrays considered somewhat harmful, then your question would be moot as you would write:

var myArray = new List<int>(Enumerable.Repeat(-1, 100));

Solution 4:

I highly doubt that the JIT will optimize away the default set for this scenario. The reason being is that this would be an observable difference. Consider the following slightly altered scenario.

obj.myArray = new int[100];
for (int i=0; i<myArray.Length; i++) { obj.myArray[i] = -1; }

It's entirely possible for the loop to throw. At least, it's probably not possible for the JIT to prove it doesn't. If it did throw and the CLR did not default initialize the memory, the result would be observable if you still had a reference to obj.