web-dev-qa-db-fra.com

Comment définir dynamiquement la longueur d'un tableau en c #

Je suis encore nouveau en C # et j'ai eu du mal à résoudre divers problèmes liés aux tableaux. J'ai un tableau d'objets de métadonnées (paires nom-valeur) et j'aimerais savoir comment créer uniquement le nombre d'objets "InputProperty" dont j'ai vraiment besoin. Dans cette boucle, j'ai arbitrairement fixé le nombre d'éléments à 20 et j'essaie de renflouer lorsque l'entrée devient nulle, mais le service Web à la réception de celui-ci n'aime pas les éléments nuls qui lui sont transmis:

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

En résumé, disons que je n'ai que 3 paires namevalue dans le tableau d'entrée ci-dessus? Plutôt que d’allouer 20 éléments pour le tableau appelé ip, comment peut-on coder cela de façon que ip soit aussi gros que nécessaire? L'objet de mise à jour étant passé sur un autre service Web, la sérialisation est donc importante (par exemple, je ne peux pas utiliser namevaluecollection, etc.). 

p.s. Est-ce que le seul moyen de donner suite à une question postée via la fonction "ajouter des commentaires"?

21
John Adams

Si vous ne souhaitez pas utiliser une variable List, ArrayList ou une autre collection de taille dynamique, puis la convertir en tableau (c'est la méthode que je recommanderais d'ailleurs), vous devrez alors allouer le tableau à son tableau. taille maximale possible, gardez une trace du nombre d'éléments que vous avez insérés, puis créez un nouveau tableau contenant uniquement ces éléments:

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

Une autre méthode serait d’assigner toujours update.Items = ip; et de redimensionner le cas échéant:

update.Items = ip;
if (i < nvPairs.Length)
{
    Array.Resize(update.Items, i);
}

C'est moins de code, mais finira probablement par faire le même travail (c'est-à-dire créer un nouveau tableau et copier les anciens éléments).

20
Jim Mischel
InputProperty[] ip = new InputProperty[nvPairs.Length]; 

Ou, vous pouvez utiliser une liste comme celle-ci:

List<InputProperty> list = new List<InputProperty>();
InputProperty ip = new (..);
list.Add(ip);
update.items = list.ToArray();

Une autre chose que je voudrais souligner, en C #, vous pouvez supprimer votre utilisation de la variable int dans une boucle for dans la boucle:

for(int i = 0; i<nvPairs.Length;i++
{
.
.
}

Et juste parce que je suis d'humeur là, voici une façon plus propre de faire cette méthode 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;
}
27
BFree

Est-il nécessaire d'être un tableau? Si vous utilisez un ArrayList ou l'un des autres objets disponibles en C #, vous n'aurez pas cette limitation de contenu. Hashtable, IDictionnary, IList, etc. permettent tous un nombre d'éléments dynamique.

5
Brian

Utilisez ceci:

 Array.Resize(ref myArr, myArr.Length + 5);
4
kilan

Vous pouvez utiliser List dans la méthode et le transformer en tableau à la fin. Mais je pense que si nous parlons d'une valeur maximale de 20, votre code est plus rapide.

    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;
    }
2
Michael Piendl

Ou en C # 3.0 en utilisant System.Linq, vous pouvez ignorer la liste intermédiaire:

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
dahlbyk

Utilisez Array.CreateInstance pour créer un tableau de manière dynamique.

    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;
    }
1
Johannes

Vous pouvez créer un tableau dynamiquement de cette façon:

 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
lukaszk

En règle générale, les tableaux nécessitent des constantes pour initialiser leur taille. Vous pouvez balayer une fois nvPairs pour obtenir la longueur, puis créer "dynamiquement" un tableau en utilisant une variable de longueur comme celle-ci.

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

Je ne le recommanderais pas, cependant. Juste coller avec le

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

solution. Ce n'est pas beaucoup moins performant et beaucoup plus beau.

0
Michael Meadows