4 votes

c# effacer une liste vs assigner une nouvelle liste à une variable existante

J'apprends le C#.

Si je crée d'abord une variable pour contenir une liste.

List<int> mylist = new List<int>();

Disons que j'ai fait un certain travail avec la liste, et que maintenant je veux effacer la liste pour l'utiliser pour quelque chose d'autre :

Méthode 1 :

mylist.Clear();

Méthode 2 :

mylist = new List<int>();

Le but est juste de vider toutes les valeurs de la liste pour réutiliser la liste.

Y a-t-il des effets secondaires à l'utilisation de la méthode 2 ? Dois-je privilégier une méthode plutôt qu'une autre ?


J'ai également trouvé une question similaire, Utilisation de la méthode "claire" vs. Nouvel objet Je laisserai les autres lecteurs décider de ce qui est le mieux pour leur propre cas d'utilisation. Je ne vais donc pas choisir une réponse correcte.

1 votes

Si vous le faites List<int> mylist = new List<int>(); Vous créez ainsi une nouvelle liste prête à l'emploi. Il n'est pas nécessaire de l'effacer, elle est prête à être utilisée, il suffit d'y accéder par l'intermédiaire de votre variable ( mylist ) qui y fait référence. Si vous réaffectez la liste ( mylist = new List<int>(); ), alors l'ancienne liste n'est plus référencée par votre code (s'il n'y a pas d'autres références à cette liste, alors elle est prête pour la fonction Collecte des ordures ) et vous créez une nouvelle liste. Votre liste mylist contient maintenant une référence à cette nouvelle liste, et elle est prête à être utilisée de la même manière.

0 votes

L'effacement permettra d'éviter l'allocation et la collecte inutiles de GC, mais laissera plus de mémoire allouée ... la question est donc principalement basée sur l'option : vitesse vs utilisation de la mémoire.

3 votes

Le seul autre facteur réel est la présence d'autres références partagées dans cette liste. Si vous l'effacez, ces références continuent d'utiliser la liste partagée. En l'effaçant, cette partie du code abandonne l'ancienne liste et commence à en utiliser une nouvelle, de sorte que les modifications apportées après ce point ne seront pas reflétées dans les autres références partagées.

7voto

CodeMonkey Points 299

L'utilisation de la méthode 2 peut entraîner un comportement inattendu dans votre programme, selon la façon dont vous utilisez la liste.

Si tu devais faire quelque chose comme :

List<int> myList = new List<int> { 1, 2, 3 };

someObj.listData = myList;

myList = new List<int>(); // clearing the list.

les données dans "someObj" seront toujours 1,2,3.

Toutefois, si vous utilisez myList.clear() à la place, les données contenues dans "someObj" seront également effacées.

Une pensée supplémentaire que je viens d'avoir. Si vous avez des références pendantes à la liste originale, et que vous réassignez la variable en utilisant new afin de l'effacer, la GC ne nettoiera jamais cette mémoire. Je dirais qu'il est toujours plus sûr d'utiliser la méthode .clear() si vous devez vider le contenu d'une liste.

2voto

Mike Cheel Points 3883

La méthode 2 entraîne une réaffectation, tandis que la méthode 1 vide simplement le tableau interne pour que le ramasseur d'ordures puisse récupérer la mémoire :

De la source :

// Clears the contents of List.
public void Clear() {
    if (_size > 0)
    {
        Array.Clear(_items, 0, _size); // Don't need to doc this but we clear the elements so that the gc can reclaim the references.
        _size = 0;
    }
    _version++;
}

https://referencesource.microsoft.com/#mscorlib/system/collections/generic/list.cs,2765070d40f47b98

I pensez à la réaffectation sera moins coûteuse que l'effacement du tableau. Dans tous les cas, les performances sont probablement négligeables, à moins que vous ne fassiez un travail vraiment très intensif. Dans ce cas, vous devriez probablement envisager d'utiliser une structure de données plus rapide qu'une liste de toute façon.

1 votes

alors que la méthode 1 ne fait qu'effacer le tableau interne pour que le ramasse-miettes puisse récupérer la mémoire pas vrai la première méthode n'entraînera pas de travaux de GC éditer : ... pour la liste elle-même - bien sûr, si la liste devait stocker un objet autre que les primitives, elle le ferait... mais encore une fois, pour List<int> il n'y aura pas de travail de la CG

0 votes

Et sur Array.Clear C'est probablement simple RtlSecureZeroMemory(*_items, size*sizeof(T)) sur la plateforme Windows (pour les primitives)... quand "réallocation" est alloc+créer une nouvelle instance de Liste, alloc+créer tous les champs de la classe Liste ... et alloc en .net n'est pas simple RtlAllocateHeap ... vous devez créer un pointeur pour le GC, etc. etc. (encore une fois pour List<int>)

1voto

Menahem Points 1539

Y a-t-il des effets secondaires à l'utilisation de la méthode 2 ? Oui. Premièrement, il y a une allocation d'un nouvel objet, Ensuite, la première liste pourrait être collectée lors du prochain passage du ramasseur de déchets.

Dois-je privilégier une méthode plutôt qu'une autre ? Vous devez privilégier la première méthode, car elle exprime plus clairement votre intention de vider la liste.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X