EDIT
I was musing on a more fully featured implementation of my answer, I thought I'd append. I'm not sure if the parallelization would help, perhaps it depends on the initializer
.
using System;
using System.Linq;
public static T[][][] NewJagged<T>(
int h,
int w,
ing d,
Func<int, int, int, T> initializer = null,
bool parallelize = true)
{
if (h < 1)
{
throw new ArgumentOutOfRangeException("h", h, "Dimension less than 1.")
}
if (w < 1)
{
throw new ArgumentOutOfRangeException("w", w, "Dimension less than 1.")
}
if (d < 1)
{
throw new ArgumentOutOfRangeException("d", d, "Dimension less than 1.")
}
if (initializer == null)
{
initializer = (i, j, k) => default(T);
}
if (parallelize)
{
return NewJaggedParalellImpl(h, w, d, initializer);
}
return NewJaggedImpl(h, w, d, initializer);
}
private static T[][][] NewJaggedImpl<T>(
int h,
int w,
int d,
Func<int, int, int, T> initializer)
{
var result = new T[h][][];
for (var i = 0; i < h; i++)
{
result[i] = new T[w][];
for (var j = 0; j < w; j++)
{
result[i][j] = new T[d];
for (var k = 0; k < d; k++)
{
result[i][j][k] = initializer(i, j, k);
}
}
}
return result;
}
private static T[][][] NewJaggedParalellImpl<T>(
int h,
int w,
int d,
Func<int, int, int, T> initializer)
{
var result = new T[h][][];
ParallelEnumerable.Range(0, h).ForAll(i =>
{
result[i] = new T[w][];
ParallelEnumerable.Range(0, w).ForAll(j =>
{
result[i][j] = new T[d];
ParallelEnumerable.Range(0, d).ForAll(k =>
{
result[i][j][k] = initializer(i, j, k);
});
});
});
return result;
}
This makes the function completely generic but still leaves you the simple syntax,
var foo1 = NewJagged<Foo>(1000, 1000, 500);
You could however get fancy and populate in paralell on initialization,
var foo2 = NewJagged<Foo>(
1000,
1000,
5000,
(i, j, k) =>
{
var pos = (i * 1000 * 500) + (j * 500) + k;
return ((pos % 2) == 0) ? new Foo() : null;
});
in this instance, populating with a checkerboard effect (I think.);
This may not initially seem to answer your problem ...
If you had a function, something like this
public static T[][][] ThreeDimmer<T>(int h, int w, int d) where T : new()
{
var result = new T[h][][];
for (var i = 0; i < h; i++)
{
result[i] = new T[w][];
for (var j = 0; j < w; j++)
{
result[i][j] = new T[d];
for (var k = 0; k < d; k++)
{
result[i][j][k] = new T();
}
}
}
return result;
}
Then you would have encapsulated the initialization of a 3 dimensional jagged array of reference types. This would allow you to do,
Foo[][][] foo1 = ThreeDimmer<Foo>(1000, 1000, 500);
This would avoid the memory fragmentation issues of multidimensional arrays. It would also avoid other pitfalls and limitations, giving you a faster more flexible jagged array instead.