I'm not a big fan of this method because of the memory usage involved, but if you use the arrays it produces, it isn't such a waste.
public static void ForEachRow<T>(this T[,] list, Action<int, T[]> action)
{
var len = list.GetLength(0);
var sub = list.GetLength(1);
T[] e;
int i, j;
for (i = 0; i < len; i++)
{
e = new T[sub];
for (j = 0; j < sub; j++)
{
e[j] = list[i, j];
}
action(i, e);
}
}
Implementation:
var list = new[,]{0x0, 0x1, 0x2, 0x4, 0x8};
list.ForEachRow((i, row) =>
{
for (var j = 0; j < row.Length; j++)
{
Console.WriteLine("[{0},{1}]: {2}", i, j, row[j]);
}
});
The other solution I found is less memory intensive, but will use more CPU, especially when the dimensions of the arrays' entries are larger.
public static void ForEachRow<T>(this T[,] list, Action<int, IEnumerable<T>> action)
{
var len = list.GetLength(0);
var sub = list.GetLength(1);
int i, j;
IEnumerable<T> e;
for (i = 0; i < len; i++)
{
e = Enumerable.Empty<T>();
for (j = 0; j < sub; j++)
{
e = e.Concat(AsEnumerable(list[i, j]));
}
action(i, e);
}
}
private static IEnumerable<T> AsEnumerable<T>(T add)
{
yield return add;
}
Implementation:
var list = new[,]{0x0, 0x1, 0x2, 0x4, 0x8};
list.ForEachRow((i, row) =>
{
var j = 0;
forrach (var o in row)
{
Console.WriteLine("[{0},{1}]: {2}", i, j, o);
++j;
}
});
As a whole, I find the first option to be more intuitive, especially if you want to access the produced array by its indexer.
At the end of the day, this is all just eye candy, neither methods should really be used in favour of directly accessing the source array;
for (var i = 0; i < list.GetLength(0); i++)
{
foreach (var j = 0; j < list.GetLength(1); j++)
{
Console.WriteLine("[{0},{1}]: {2}", i, j, list[i, j]);
}
}