Я хочу построить двумерный массив строк, длина одного измерения которого равна 2. Аналогично этому
string[,] array = new string[,]
{
{"a", "b"},
{"c", "d"},
{"e", "f"},
{"g", "h"}
}
Делает
List<string[]> list = new List<string[]>();
list.Add(new string[2] {"a", "b"});
list.Add(new string[2] {"c", "d"});
list.Add(new string[2] {"e", "f"});
list.Add(new string[2] {"g", "h"});
list.ToArray();
дает мне
string[][]
но нет
string[,]
множество.
Просто любопытно, есть ли какой-нибудь трюк для динамического построения
string[,]
массив как-нибудь?





Это невозможно с List<string[]>, поскольку тип string[,] отличается от string[].
Единственный способ сделать это - реализовать функцию ToArray() самостоятельно. Вы можете реализовать это в своей собственной коллекции (например, StringTupleCollection). Это может работать так же, как ArrayList (т.е. внутренний массив увеличивается в размере по мере необходимости).
Однако я не уверен, что преимущество [x,2] перед [x][2] (или даже List<string[2]> было бы достаточно значительным, чтобы оправдать усилия.
Вы также можете написать класс StringTupple как:
public class StringTupple : KeyValuePair<string, string>
{
}
Что ж, вы могли бы легко написать для этого метод расширения. Что-то вроде этого (проверено совсем немного):
public static T[,] ToRectangularArray<T>(this IEnumerable<T[]> source)
{
if (!source.Any())
{
return new T[0,0];
}
int width = source.First().Length;
if (source.Any(array => array.Length != width))
{
throw new ArgumentException("All elements must have the same length");
}
T[,] ret = new T[source.Count(), width];
int row = 0;
foreach (T[] array in source)
{
for (int col=0; col < width; col++)
{
ret[row, col] = array[col];
}
row++;
}
return ret;
}
Жаль, что в приведенном выше коде в качестве типа элемента используется T []. Из-за общей инвариантности я в настоящее время не могу сделать исходный IEnumerable<IEnumerable<T>>, что было бы неплохо. Альтернативой может быть введение нового параметра типа с ограничением:
public static T[,] ToRectangularArray<T,U>(this IEnumerable<U> source)
where U : IEnumerable<T>
Немного волосатое, но должно работать. (Очевидно, что реализация тоже нуждается в некоторых изменениях, но основной принцип тот же.)
Это невозможно сделать во время компиляции или с самим List <T>. Есть еще один класс (не могу вспомнить имя в данный момент), который позволит вам проверять записи по мере их добавления, но только во время выполнения.
Ты можешь сделать это.
List<KeyValuePair<string, string>>
Идея состоит в том, что пара ключевых значений имитирует массив строк, которые вы реплицировали.
KeyValuePair не работал у меня, когда мне приходилось получать значения флажков на контроллере в качестве моей модели. Список ролей был нулевым.
foreach (KeyValuePair<string, bool> Role in model.Roles){...}
Структура KeyValuePair не имеет конструктора без параметров по умолчанию и не может быть создана связывателем модели. Я рекомендую пользовательский класс модели для вашего представления, который имеет только эти свойства. Привязка пользовательского элемента управления типа KeyValuePair к ViewModel в ASP.NET MVC 3
Я нашел реализацию списка флажков без использования помощника html по следующей ссылке CheckboxList в MVC3.0
Вы можете просто использовать struct. Я делаю это при сравнении узлов XML вручную.
private struct XmlPair
{
public string Name { set; get; }
public string Value { set; get; }
}
List<XmlPair> Pairs = new List<XmlPair>();
Очень хорошо! Меня все еще интересует, можно ли каким-то образом определить List <>, чтобы заставить его принимать только двухэлементные строковые массивы?