Как установить длину массива в C # динамически - PullRequest
21 голосов
/ 25 марта 2009

Я все еще новичок в 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 и т. Д.).

p.s. Является ли единственный способ следить за опубликованным вопросом с помощью функции «Добавить комментарий»?

Ответы [ 9 ]

27 голосов
/ 25 марта 2009
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++
{
.
.
}

И только потому, что я в настроении, вот более чистый способ сделать этот метод ИМО:

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;
}
20 голосов
/ 25 марта 2009

Если вы не хотите использовать 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);
}

Это меньше кода, но, скорее всего, он будет выполнять ту же работу (т. Е. Создавать новый массив и копировать старые элементы).

5 голосов
/ 25 марта 2009

Должен ли быть массив? Если вы используете ArrayList или один из других объектов, доступных в C #, у вас не будет этого ограничения на контент с. Hashtable, IDictionnary, IList и т. Д. Все позволяют динамическое количество элементов.

4 голосов
/ 08 августа 2012

Используйте это:

 Array.Resize(ref myArr, myArr.Length + 5);
2 голосов
/ 25 марта 2009

Или в 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;
}
2 голосов
/ 25 марта 2009

Вы можете использовать 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;
    }
1 голос
/ 24 августа 2012

Используйте 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;
    }
0 голосов
/ 21 декабря 2012

Вы можете создать массив динамически следующим образом:

 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];

    }
0 голосов
/ 25 марта 2009

Как правило, массивам требуются константы для инициализации их размера. Вы можете выполнить nvPairs один раз, чтобы получить длину, а затем «динамически» создать массив, используя переменную для длины, подобную этой.

InputProperty[] ip = (InputProperty[])Array.CreateInstance(typeof(InputProperty), length);

Я бы не советовал. Просто придерживайтесь

List<InputProperty> ip = ...
...
update.Items = ip.ToArray();

решение. Это не намного менее производительный, и намного лучше выглядящий.

...