Я не большой поклонник этого метода из-за задействованного использования памяти, но если вы используете создаваемые им массивы, это не такая трата.
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);
}
}
Реализация:
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]);
}
});
Другое решение, которое я нашел, требует меньше памяти, но будет использовать больше ЦП, особенно когда размеры записей массивов больше.
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;
}
Реализация:
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;
}
});
В целом, я считаю, что первый вариант более интуитивно понятен, особенно если вы хотите получить доступ к производимому массиву с помощью его индексатора.
В конце концов, это всего лишь конфетка, ни один из методов не должен использоваться для прямого доступа к исходному массиву;
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]);
}
}