Как установить длину массива в C# динамически
Я все еще новичок в C#, и я боролся с различными проблемами на массивах. У меня есть массив объектов метаданных (пары "имя-значение"), и я хотел бы знать, как создать только то количество объектов "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 пары namevalue в указанном выше массиве ввода? Вместо того, чтобы выделять 20 элементов для массива, называемого ip, как это можно кодировать, чтобы ip был настолько большим, насколько это необходимо. Объект обновления передается через другой веб-сервис, поэтому сериализация важна (т.е. я не могу использовать namevaluecollection и т. Д.).
ps Является ли единственный способ следить за опубликованным вопросом с помощью функции "Добавить комментарий"?
9 ответов
Если вы не хотите использовать 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);
}
Это меньше кода, но, вероятно, в конечном итоге выполнить тот же объем работы (например, создание нового массива и копирование старых элементов).
InputProperty[] ip = new InputProperty[nvPairs.Length];
Или вы можете использовать список следующим образом:
List<InputProperty> list = new List<InputProperty>();
InputProperty ip = new (..);
list.Add(ip);
update.items = list.ToArray();
Еще одна вещь, на которую я хотел бы обратить внимание: в C# вы можете исключить использование переменной 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;
}
Использовать этот:
Array.Resize(ref myArr, myArr.Length + 5);
Должен ли быть массив? Если вы используете ArrayList или один из других объектов, доступных в C#, у вас не будет этого ограничения на контент с. Hashtable, IDictionnary, IList и т. Д. Все позволяют динамическое количество элементов.
Вы можете использовать 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;
}
Использование 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;
}
Или в C# 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;
}
Вы можете создать массив динамически следующим образом:
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];
}
Как правило, для массивов требуются константы для инициализации их размера. Вы можете провести nvPairs один раз, чтобы получить длину, а затем "динамически" создать массив, используя переменную для длины, подобную этой.
InputProperty[] ip = (InputProperty[])Array.CreateInstance(typeof(InputProperty), length);
Я не рекомендовал бы это, все же. Просто придерживайтесь
List<InputProperty> ip = ...
...
update.Items = ip.ToArray();
решение. Это не намного менее производительный, и намного лучше выглядящий.