У меня есть двухмерная антенная решетка,
string[,] table = {
{ "aa", "aaa" },
{ "bb", "bbb" }
};
И я хотел бы foreach
через него как это,
foreach (string[] row in table)
{
Console.WriteLine(row[0] + " " + row[1]);
}
Но, я получаю ошибку:
Не может преобразовать строку типа для строкового представления []
Существует ли способ, которым я могу достигнуть того, что я хочу, т.е. выполняю итерации через первый размер массива с переменной итератора возврата меня одномерный массив для той строки?
Если вы определяете свой массив следующим образом:
string[][] table = new string[][] { new string[] { "aa", "aaa" }, new string[]{ "bb", "bbb" } };
Тогда вы можете использовать для него цикл foreach.
Многомерные массивы нельзя перечислить. Просто повторите старый добрый способ:
for (int i = 0; i < table.GetLength(0); i++)
{
Console.WriteLine(table[i, 0] + " " + table[i, 1]);
}
Как предлагали другие, вы можете использовать вложенные циклы for или повторно объявить свой многомерный массив как зубчатый.
Однако я думаю, что стоит отметить, что многомерные массивы перечислимы, но не так, как вы хотите. Например:
string[,] table = {
{ "aa", "aaa" },
{ "bb", "bbb" }
};
foreach (string s in table)
{
Console.WriteLine(s);
}
/* Output is:
aa
aaa
bb
bbb
*/
ОБНОВЛЕНИЕ : у меня было немного свободного времени, так что ... Я пошел дальше и конкретизировал эту идею. Смотрите код ниже.
Вот немного сумасшедший ответ:
Вы можете делать то, что ищете - по сути, обрабатывать двумерный массив как таблицу со строками - написав статический метод (возможно, метод расширения), который принимает T [,]
и возвращает IEnumerable
. Однако для этого потребуется скопировать каждую «строку» базовой таблицы в новый массив.
Возможно, лучшим (хотя и более сложным) подходом было бы написание класса, реализующего IList
как оболочку вокруг единственной «строки» двумерного массива (вы, вероятно, установите IsReadOnly
в значение true и просто реализуйте геттер для свойства this [int]
и, возможно, Count
и GetEnumerator
; все остальное может выбросить a NotSupportedException
). Тогда ваш статический метод / метод расширения может вернуть IEnumerable
и обеспечить отложенное выполнение.
Таким образом, вы могли писать код, очень похожий на ваш:
foreach (IList<string> row in table.GetRows()) // or something
{
Console.WriteLine(row[0] + " " + row[1]);
}
Просто мысль.
Предложение по реализации:
public static class ArrayTableHelper {
public static IEnumerable<IList<T>> GetRows<T>(this T[,] table) {
for (int i = 0; i < table.GetLength(0); ++i)
yield return new ArrayTableRow<T>(table, i);
}
private class ArrayTableRow<T> : IList<T> {
private readonly T[,] _table;
private readonly int _count;
private readonly int _rowIndex;
public ArrayTableRow(T[,] table, int rowIndex) {
if (table == null)
throw new ArgumentNullException("table");
if (rowIndex < 0 || rowIndex >= table.GetLength(0))
throw new ArgumentOutOfRangeException("rowIndex");
_table = table;
_count = _table.GetLength(1);
_rowIndex = rowIndex;
}
// I didn't implement the setter below,
// but you easily COULD (and then set IsReadOnly to false?)
public T this[int index] {
get { return _table[_rowIndex, index]; }
set { throw new NotImplementedException(); }
}
public int Count {
get { return _count; }
}
bool ICollection<T>.IsReadOnly {
get { return true; }
}
public IEnumerator<T> GetEnumerator() {
for (int i = 0; i < _count; ++i)
yield return this[i];
}
// omitted remaining IList<T> members for brevity;
// you actually could implement IndexOf, Contains, etc.
// quite easily, though
}
}
... теперь я думаю, что мне следует дать StackOverflow перерыв на остаток дня;)
Помните, что многомерный массив подобен таблице. У вас нет элемента x и элемента y для каждой записи; у вас есть строка в (например) table[1,2]
.
Таким образом, каждая запись по-прежнему является только одной строкой (в вашем примере), это просто запись в определенном значении x/y. Поэтому, чтобы получить обе записи в table[1, x]
, вы должны сделать вложенный цикл for. Что-то вроде следующего (не проверялось, но должно быть близко)
for (int x = 0; x < table.Length; x++)
{
for (int y = 0; y < table.Length; y += 2)
{
Console.WriteLine("{0} {1}", table[x, y], table[x, y + 1]);
}
}