C# 使用常量值直接初始化数组

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/648814/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 11:43:47  来源:igfitidea点击:

Direct array initialization with a constant value

c#arraysinitializationconstants

提问by Rauhotz

Whenever you allocate a new array in C# with

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

new T[length]

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

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

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

在我的情况下,我想Int32用值 -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.

因此,在为数组保留内存后,CLR 会遍历新分配的内存并将所有条目设置为 default(int) = 0。之后,我的代码将所有条目设置为 -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?

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

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

参考C# 数组初始化 - 使用非默认值,使用Enumerable.Repeat(value, length).ToArray()是没有选择的,因为Enumerable.ToArray分配一个新数组并在之后将值复制到它。

采纳答案by Jon Skeet

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.

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

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

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

回答by JaredPar

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.

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

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.

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

回答by Dаn

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

如果您购买被认为有点有害的 Arrays,那么您的问题将像您所写的那样没有实际意义:

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

回答by Taylor Leese

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

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

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

回答by Martin Zikmund

I suggest using Array.Fillas a very succint way to fill an array with an initial value:

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

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

This initializes all values in the isPrimearray to true.

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

回答by Hardik

If you are looking for one liner solution then you could use below:

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

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