views:

979

answers:

4

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 intialization 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.

+8  A: 

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".

Jon Skeet
I don't see where an exception could be thrown. The JIT is intelligent enough to disable range checks on the array within the loop, so it could also detect that no exception can occur.
Rauhotz
@Rauhotz ThreadAbortException can be thrown at any time.
JaredPar
OK, that's a point
Rauhotz
+1  A: 

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.

JaredPar
Constrain the problem to local variables.
Rauhotz
@Rauhotz, at that point you have to start questioning whether or not the optimization is worth it. You've now limited it to a very constrained scenario.
JaredPar
A: 

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

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

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

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