Как установить длину массива в С# динамически
Я все еще новичок в С#, и я боролся с различными проблемами в массивах. У меня есть массив объектов метаданных (пары значений имени), и я хотел бы знать, как создать только количество объектов "InputProperty", которые мне действительно нужны. В этом цикле я произвольно установил количество элементов в 20, и я попытаюсь выручить, когда запись станет пустой, но веб-служба на принимающей стороне этого не понравится ни одному из нулевых элементов, переданных ей:
private Update BuildMetaData(MetaData[] nvPairs)
{
Update update = new Update();
InputProperty[] ip = new InputProperty[20]; // how to make this "dynamic"
int i;
for (i = 0; i < nvPairs.Length; i++)
{
if (nvPairs[i] == null) break;
ip[i] = new InputProperty();
ip[i].Name = "udf:" + nvPairs[i].Name;
ip[i].Val = nvPairs[i].Value;
}
update.Items = ip;
return update;
}
В общем, скажем, у меня есть только 3 пары имени в вышеприведенном массиве ввода? Вместо того, чтобы выделять 20 элементов для массива с именем ip, как это сделать, так что ip настолько велик, насколько это необходимо. Объект обновления передается через другой веб-сервис, поэтому важна сериализация (т.е. Я не могу использовать namevaluecollection и т.д.).
p.s. Это единственный способ отслеживания размещенного вопроса через объект "добавить комментарии"?
Ответы
Ответ 1
Если вы не хотите использовать List
, ArrayList
или другую коллекцию с динамическим размером, а затем конвертировать в массив (что метод, который я рекомендую, кстати), то вы будете нужно выделить массив до максимально возможного размера, отслеживать количество элементов, которые вы в него вложили, а затем создать новый массив с помощью только тех элементов в нем:
private Update BuildMetaData(MetaData[] nvPairs)
{
Update update = new Update();
InputProperty[] ip = new InputProperty[20]; // how to make this "dynamic"
int i;
for (i = 0; i < nvPairs.Length; i++)
{
if (nvPairs[i] == null) break;
ip[i] = new InputProperty();
ip[i].Name = "udf:" + nvPairs[i].Name;
ip[i].Val = nvPairs[i].Value;
}
if (i < nvPairs.Length)
{
// Create new, smaller, array to hold the items we processed.
update.Items = new InputProperty[i];
Array.Copy(ip, update.Items, i);
}
else
{
update.Items = ip;
}
return update;
}
Альтернативным методом было бы всегда назначать update.Items = ip;
, а затем при необходимости изменять размер:
update.Items = ip;
if (i < nvPairs.Length)
{
Array.Resize(update.Items, i);
}
Это меньше кода, но, скорее всего, закончится тем же объемом работы (т.е. создаст новый массив и скопирует старые элементы).
Ответ 2
InputProperty[] ip = new InputProperty[nvPairs.Length];
Или вы можете использовать такой список:
List<InputProperty> list = new List<InputProperty>();
InputProperty ip = new (..);
list.Add(ip);
update.items = list.ToArray();
Еще одна вещь, которую я хотел бы отметить, в С# вы можете использовать вашу переменную int в цикле for прямо внутри цикла:
for(int i = 0; i<nvPairs.Length;i++
{
.
.
}
И только потому, что я в настроении, здесь более чистый способ сделать этот метод IMO:
private Update BuildMetaData(MetaData[] nvPairs)
{
Update update = new Update();
var ip = new List<InputProperty>();
foreach(var nvPair in nvPairs)
{
if (nvPair == null) break;
var inputProp = new InputProperty
{
Name = "udf:" + nvPair.Name,
Val = nvPair.Value
};
ip.Add(inputProp);
}
update.Items = ip.ToArray();
return update;
}
Ответ 3
Нужно ли быть массивом? Если вы используете ArrayList или один из других объектов, доступных на С#, у вас не будет этого ограничения для контента. Hashtable, IDictionnary, IList и т.д. Все позволяют динамическое количество элементов.
Ответ 4
Используйте это:
Array.Resize(ref myArr, myArr.Length + 5);
Ответ 5
Вы можете использовать List внутри метода и преобразовать его в массив в конце. Но я думаю, что если мы говорим о максимальном значении 20, ваш код будет быстрее.
private Update BuildMetaData(MetaData[] nvPairs)
{
Update update = new Update();
List<InputProperty> ip = new List<InputProperty>();
for (int i = 0; i < nvPairs.Length; i++)
{
if (nvPairs[i] == null) break;
ip[i] = new InputProperty();
ip[i].Name = "udf:" + nvPairs[i].Name;
ip[i].Val = nvPairs[i].Value;
}
update.Items = ip.ToArray();
return update;
}
Ответ 6
Или в С# 3.0 с помощью System.Linq
вы можете пропустить промежуточный список:
private Update BuildMetaData(MetaData[] nvPairs)
{
Update update = new Update();
var ip = from nv in nvPairs
select new InputProperty()
{
Name = "udf:" + nv.Name,
Val = nv.Value
};
update.Items = ip.ToArray();
return update;
}
Ответ 7
Используйте Array.CreateInstance
для динамического создания массива.
private Update BuildMetaData(MetaData[] nvPairs)
{
Update update = new Update();
InputProperty[] ip = Array.CreateInstance(typeof(InputProperty), nvPairs.Count()) as InputProperty[];
int i;
for (i = 0; i < nvPairs.Length; i++)
{
if (nvPairs[i] == null) break;
ip[i] = new InputProperty();
ip[i].Name = "udf:" + nvPairs[i].Name;
ip[i].Val = nvPairs[i].Value;
}
update.Items = ip;
return update;
}
Ответ 8
Обычно для массивов требуются константы для инициализации их размера. Вы можете прокручивать nvPairs один раз, чтобы получить длину, а затем "динамически" создать массив, используя переменную длиной, подобной этой.
InputProperty[] ip = (InputProperty[])Array.CreateInstance(typeof(InputProperty), length);
Я бы не рекомендовал его. Просто придерживайтесь
List<InputProperty> ip = ...
...
update.Items = ip.ToArray();
решение. Это не намного менее результативно, а лучше выглядит.
Ответ 9
Вы можете создать массив динамически следующим образом:
static void Main()
{
// Create a string array 2 elements in length:
int arrayLength = 2;
Array dynamicArray = Array.CreateInstance(typeof(int), arrayLength);
dynamicArray.SetValue(234, 0); // → a[0] = 234;
dynamicArray.SetValue(444, 1); // → a[1] = 444;
int number = (int)dynamicArray.GetValue(0); // → number = a[0];
int[] cSharpArray = (int[])dynamicArray;
int s2 = cSharpArray[0];
}