每当您在C#中使用
分配新数组时new T[length]
数组条目设置为默认值T.对于null
是引用类型或T
的默认构造函数的结果,T
,T
{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
会分配一个新数组,然后将值复制到其中。
答案 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);