使用常量值进行直接数组初始化

时间:2009-03-15 23:37:29

标签: c# arrays initialization constants

每当您在C#中使用

分配新数组时
new T[length]

数组条目设置为默认值T.对于null是引用类型或T的默认构造函数的结果,TT {1}}是一种值类型。

在我的情况下,我想初始化一个Int32数组,其值为-1:

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

因此,在为数组保留内存之后,CLR遍历新分配的内存并将所有条目设置为default(int)= 0.之后,我的代码将所有条目设置为-1。

这使初始化变得多余。 JIT是否检测到这一点并忽略初始化为0,如果没有,是否有办法用自定义值直接初始化一部分内存?

参考C# Array initialization - with non-default value ,使用Enumerable.Repeat(value, length).ToArray()是不可取的,因为Enumerable.ToArray会分配一个新数组,然后将值复制到其中。

6 个答案:

答案 0 :(得分:33)

这不是多余的。

假设在初始化循环期间抛出异常。如果CLR尚未首先清除内存,您可能能够“看到”原始的未初始化内存,这是一个非常糟糕的主意,特别是从安全角度来看。这就是CLR保证将任何新分配的内存擦除为0位模式的原因。

顺便提一下,对象中的字段也适用。

我认为在这两种情况下,CLR都可以在完成初始化之前检查你是否打算在其他地方看到数组,但这是一个复杂的检查,以避免一个非常简单的“擦除这个内存区域”。

答案 1 :(得分:31)

与Dan的答案相似,但不需要使用集合:

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

答案 2 :(得分:10)

如果你买入Arrays considered somewhat harmful,那么你的问题就像你写的那样没有实际意义:

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

答案 3 :(得分:3)

我非常怀疑JIT会优化此方案的默认设置。原因是这将是一个可观察到的差异。请考虑以下略有改变的情况。

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

循环完全有可能抛出。至少,JIT可能无法证明它没有。如果它确实抛出并且CLR没有默认初始化内存,那么如果你仍然有对obj的引用,结果将是可观察的。

答案 4 :(得分:0)

我建议使用OfType作为用初始值填充数组的一种非常简洁的方法:

Array.Fill

这会将bool[] isPrime = new bool[MaxNum]; Array.Fill(isPrime, true); 数组中的所有值初始化为isPrime

答案 5 :(得分:0)

如果您正在寻找一种衬管解决方案,则可以在下面使用:

var myArray = Array.ConvertAll(new int[100], i => -1);