web-dev-qa-db-fra.com

Initialisation directe d'un tableau avec une valeur constante

Chaque fois que vous allouez un nouveau tableau en C # avec 

new T[length]

les entrées du tableau sont définies sur la valeur par défaut de T. C'est null pour le cas où T est un type de référence ou le résultat du constructeur par défaut de T, si T est un type de valeur.

Dans mon cas, je veux initialiser un tableau Int32 avec la valeur -1:

var myArray = new int[100];
for (int i=0; i<myArray.Length; i++) { myArray[i] = -1; }

Ainsi, une fois que la mémoire est réservée pour le tableau, le CLR boucle sur la mémoire nouvellement allouée et définit toutes les entrées sur la valeur par défaut (int) = 0. Après cela, mon code définit toutes les entrées sur -1. 

Cela rend l’initialisation redondante. Le JIT détecte-t-il cela et néglige-t-il l'initialisation à 0? Sinon, existe-t-il un moyen d'initialiser directement une partie de la mémoire avec une valeur personnalisée?

En se référant à Initialisation du tableau C # - avec une valeur autre que la valeur par défaut , l'utilisation de Enumerable.Repeat(value, length).ToArray() n'est pas une option, car Enumerable.ToArray alloue un nouveau tableau et y copie les valeurs par la suite.

45
Rauhotz

Ce n'est pas redondant.

Supposons qu'une exception soit levée lors de votre boucle d'initialisation. Si le CLR n'a pas d'abord effacé la mémoire, vous pourrez peut-être "voir" la mémoire non initialisée d'origine, ce qui est une très mauvaise idée, en particulier du point de vue de la sécurité. C'est pourquoi le CLR garantit que toute mémoire nouvellement allouée est effacée selon un modèle à 0 bit.

Le même argument est valable pour les champs d'un objet.

Je suppose que dans les deux cas, le CLR pourrait vérifier que vous n'allez pas rendre le tableau visible ailleurs avant la fin de l'initialisation, mais c'est une vérification compliquée qui vous évite de "nettoyer cette zone de mémoire".

33
Jon Skeet

Semblable à la réponse de Dan mais sans qu'il soit nécessaire d'utiliser des collections:

int[] myArray = Enumerable.Repeat(-1, 100).ToArray();
30
Taylor Leese

Si vous achetez dans Des tableaux considérés comme quelque peu nuisibles , votre question deviendra alors sans objet comme vous l'écriviez

var myArray = new List<int>(Enumerable.Repeat(-1, 100));
10
Ðаn

Je doute fortement que le JIT optimise le paramétrage par défaut pour ce scénario. La raison en est que ce serait une différence observable. Considérez le scénario légèrement modifié suivant.

obj.myArray = new int[100];
for (int i=0; i<myArray.Length; i++) { obj.myArray[i] = -1; }

Il est tout à fait possible que la boucle soit lancée. Au moins, il n’est probablement pas possible pour l’EEC de prouver que ce n’est pas le cas. Si cela se produit et que le CLR n'initialise pas la mémoire par défaut, le résultat serait observable si vous aviez toujours une référence à obj. 

3
JaredPar

Je suggère d'utiliser Array.Fill comme moyen très succinct de remplir un tableau avec une valeur initiale:

bool[] isPrime = new bool[MaxNum];
Array.Fill(isPrime, true);

Cela initialise toutes les valeurs du tableau isPrime à true.

0
Martin Zikmund