我知道c#中实例化的值类型数组会自动填充该类型的默认值(例如bool为false, int为0,等等)。

是否有一种方法来自动填充一个不是默认的种子值的数组?无论是在创建或之后的内置方法(如Java的Arrays.fill())?假设我想要一个默认为true的布尔数组,而不是false。是否有一个内置的方法来做到这一点,或者你只需要通过一个for循环迭代数组?

 // Example pseudo-code:
 bool[] abValues = new[1000000];
 Array.Populate(abValues, true);

 // Currently how I'm handling this:
 bool[] abValues = new[1000000];
 for (int i = 0; i < 1000000; i++)
 {
     abValues[i] = true;
 }

必须遍历数组并将每个值“重置”为true似乎效率不高。还有其他方法吗?也许通过翻转所有值?

在输入这个问题并思考之后,我猜默认值只是c#在幕后处理这些对象的内存分配的结果,所以我想这可能是不可能的。但我还是想确定一下!


当前回答

Enumerable.Repeat(true, 1000000).ToArray();

其他回答

Boolean[] data = new Boolean[25];

new Action<Boolean[]>((p) => { BitArray seed = new BitArray(p.Length, true); seed.CopyTo(p, 0); }).Invoke(data);

创建一个包含1000个真值的新数组:

var items = Enumerable.Repeat<bool>(true, 1000).ToArray();  // Or ToList(), etc.

类似地,你可以生成整数序列:

var items = Enumerable.Range(0, 1000).ToArray();  // 0..999

这里给出的许多答案都可以归结为一个循环,每次初始化数组中的一个元素,它没有利用设计为一次操作内存块的CPU指令。

. net Standard 2.1(在撰写本文时的预览版中)提供了Array.Fill(),这有助于在运行时库中实现高性能(尽管到目前为止,. net Core似乎还没有利用这种可能性)。

For those on earlier platforms, the following extension method outperforms a trivial loop by a substantial margin when the array size is significant. I created it when my solution for an online code challenge was around 20% over the allocated time budget. It reduced the runtime by around 70%. In this case, the array fill was performed inside another loop. BLOCK_SIZE was set by gut feeling rather than experiment. Some optimizations are possible (e.g. copying all bytes already set to the desired value rather than a fixed-size block).

internal const int BLOCK_SIZE = 256;
public static void Fill<T>(this T[] array, T value)
{
    if (array.Length < 2 * BLOCK_SIZE)
    {
        for (int i = 0; i < array.Length; i++) array[i] = value;
    }
    else
    {
        int fullBlocks = array.Length / BLOCK_SIZE;
        // Initialize first block
        for (int j = 0; j < BLOCK_SIZE; j++) array[j] = value;
        // Copy successive full blocks
        for (int blk = 1; blk < fullBlocks; blk++)
        {
            Array.Copy(array, 0, array, blk * BLOCK_SIZE, BLOCK_SIZE);
        }

        for (int rem = fullBlocks * BLOCK_SIZE; rem < array.Length; rem++)
        {
            array[rem] = value;
        }
    }
}

对于大型数组或可变大小的数组,您可能应该使用:

Enumerable.Repeat(true, 1000000).ToArray();

对于小数组,你可以使用c# 3中的集合初始化语法:

bool[] vals = new bool[]{ false, false, false, false, false, false, false };

集合初始化语法的好处是,不必在每个槽中使用相同的值,可以使用表达式或函数初始化一个槽。另外,我认为您避免了将数组槽初始化为默认值的代价。举个例子:

bool[] vals = new bool[]{ false, true, false, !(a ||b) && c, SomeBoolMethod() };

如果你可以反转你的逻辑,你可以使用array . clear()方法将布尔数组设置为false。

        int upperLimit = 21;
        double optimizeMe = Math.Sqrt(upperLimit);

        bool[] seiveContainer = new bool[upperLimit];
        Array.Clear(seiveContainer, 0, upperLimit);