51

每当您在 C# 中分配一个新数组时

new T[length]

数组条目设置为 T的默认值。如果是值类型,则null适用于T引用类型或默认构造函数的结果的情况。TT

在我的情况下,我想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# 数组初始化 - 使用非默认值,使用Enumerable.Repeat(value, length).ToArray()是没有选项,因为Enumerable.ToArray分配一个新数组并随后将值复制到它。

4

6 回答 6

35

类似于丹的回答,但不需要使用集合:

int[] myArray = Enumerable.Repeat(-1, 100).ToArray();
于 2009-09-29T17:33:34.950 回答
33

这不是多余的。

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

顺便说一句,同样的论点也适用于对象中的字段。

我想在这两种情况下,CLR 都可以在完成初始化之前检查您是否不会使数组在其他地方可见,但这是一项复杂的检查,以避免非常简单的“擦除该内存区域”。

于 2009-03-15T23:42:30.380 回答
10

如果您购买被认为有些有害的 Arrays,那么您的问题将没有实际意义,因为您会写:

var myArray = new List<int>(Enumerable.Repeat(-1, 100));
于 2009-03-16T00:08:43.577 回答
3

我非常怀疑 JIT 是否会优化掉这个场景的默认设置。原因是这将是一个可观察到的差异。考虑以下稍微改变的场景。

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

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

于 2009-03-15T23:44:13.840 回答
2

我建议使用Array.Fill作为一种非常简洁的方式来用初始值填充数组:

bool[] isPrime = new bool[MaxNum];
Array.Fill(isPrime, true);

这会将isPrime数组中的所有值初始化为true

于 2019-01-08T13:03:49.453 回答
0

如果您正在寻找一种衬垫解决方案,那么您可以使用以下方法:

var myArray = Array.ConvertAll(new int[100], i => -1);
于 2020-04-26T16:03:35.853 回答