Самым быстрым решением является Buffer.BlockCopy:
static void ClearArray(Array array, int val)
{
var helper = Enumerable.Repeat(val, Math.Min(array.Length, 1024)).ToArray();
var itemSize = 4;
Buffer.BlockCopy(helper, 0, array, 0, helper.Length * itemSize);
for (var len = helper.Length; len < array.Length; len *= 2)
{
Buffer.BlockCopy(array, 0, array, len * itemSize, Math.Min(len, array.Length - len) * itemSize);
}
}
static int Count(Array array, Func<int, bool> predicate)
{
var helper = new int[Math.Min(array.Length, 4096)];
var itemSize = 4;
var count = 0;
for (var offset = 0; offset < array.Length; offset += helper.Length)
{
var len = Math.Min(helper.Length, array.Length - offset);
Buffer.BlockCopy(array, offset * itemSize, helper, 0, len * itemSize);
for (var i = 0; i < len; ++i)
if (predicate(helper[i]))
count++;
}
return count;
}
Статистика:
time: 00:00:00.0449501, method: Buffer.BlockCopy
time: 00:00:01.4371424, method: Lexicographical order
time: 00:00:01.3588629, method: Recursed
time: 00:00:06.2005057, method: Cartesian product with index array reusing
time: 00:00:08.2433531, method: Cartesian product w/o index array reusing
Статистика (функция подсчета):
time: 00:00:00.0812866, method: Buffer.BlockCopy
time: 00:00:02.7617093, method: Lexicographical order
Код:
Array array = Array.CreateInstance(typeof(int), new[] { 100, 200, 400 }, new[] { -10, -20, 167 });
foreach (var info in new []
{
new {Name = "Buffer.BlockCopy", Method = (Action<Array, int>)ClearArray_BufferCopy},
new {Name = "Lexicographical order", Method = (Action<Array, int>)ClearArray_LexicographicalOrder},
new {Name = "Recursed", Method = (Action<Array, int>)ClearArray_Recursed},
new {Name = "Cartesian product with index array reusing", Method = (Action<Array, int>)ClearArray_Cartesian_ReuseArray},
new {Name = "Cartesian product w/o index array reusing", Method = (Action<Array, int>)ClearArray_Cartesian},
}
)
{
var stopwatch = new Stopwatch();
stopwatch.Start();
var count = 10;
for (var i = 0; i < count; ++i)
info.Method(array, i);
stopwatch.Stop();
Console.WriteLine("time: {0}, method: {1}", TimeSpan.FromTicks(stopwatch.Elapsed.Ticks / count), info.Name);
}