foreach, performance sage. Faut-il déclarer une variable une fois avant loop ou dedans?

StackOverflow https://stackoverflow.com/questions/1632444

  •  06-07-2019
  •  | 
  •  

Question

Quoi de mieux en termes de performances: déclarer la variable en dehors de la déclaration foreach et la réaffecter à chaque fois à côté de la (foreach) ou créer une nouvelle variable dans foreach par exemple

private List<ListItem> GetItems()
        {
            var items = new List<ListItem>();
            var collection = new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            ListItem item;
            foreach (var i in collection)
            {
                item = new ListItem { Text = i.ToString() };
                items.Add(item);
            }

            return items;
        }

ou celui-ci?

private List<ListItem> GetItems()
        {
            var items = new List<ListItem>();
            var collection = new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            foreach (var i in collection)
            {
                ListItem item = new ListItem { Text = i.ToString() };
                items.Add(item);
            }

            return items;
        }

bien sûr, je parle d’objet d’objet. merci à tous.

Était-ce utile?

La solution

Cela ressemble à une optimisation prématurée . p>

Tout d’abord, avez-vous des raisons de croire qu’il ya un problème de performances ici?

Deuxièmement, dans les versions de version, l'optimiseur du compilateur produira probablement un code identique pour les deux scénarios - il est donc probablement hors de propos. Dans les versions de débogage, cela n’est peut-être pas toujours vrai, mais vous ne voulez pas d’optimisations, car l’intention des versions de débogage est de vous permettre de parcourir le code avec précision.

Autres conseils

Il existe un cas extrême où cela compte; si vous " capturez " la variable dans une méthode anonyme / lambda. Sinon, il est prématuré et ne fait aucune différence. Du tout.

Voici un exemple de ce qui compte:

// prints all items in no particular order
foreach (var i in collection)
{
    string s = i.ToString();
    ThreadPool.QueueUserWorkItem(delegate { Console.WriteLine(s); });
}

vs

// may print the same item each time, or any combination of items; very bad
string s;
foreach (var i in collection)
{
    s = i.ToString();
    ThreadPool.QueueUserWorkItem(delegate { Console.WriteLine(s); });
}

Je suis presque sûr que l'IL généré par vos deux blocs de code est identique. Il ne devrait y avoir aucun changement dans les performances. Cependant, le deuxième bloc de code dans lequel vous déclarez le type d’élément à l’usage où il est utilisé est légèrement plus lisible et j’utiliserais cela.

Il s’agit d’une très micro-optimisation et les deux méthodes auront probablement les mêmes performances, si elles ne génèrent pas un code identique. Dans ce cas, optez pour la lisibilité. Je préférerais le second, car votre objet ne sert à rien en dehors de la boucle foreach.

On pourrait soutenir que vous pourriez également vous débarrasser de la référence stockée:

private List<ListItem> GetItems()
{
  var items = new List<ListItem>();
  var collection = new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

  foreach (var i in collection)
  {
    items.Add(new ListItem { Text = i.ToString() });
  }

  return items;
}

L’IL créé par les deux blocs devrait être presque identique. Si vous cherchez à optimiser, je voudrais définir la longueur de la liste finale avant de la remplir avec des éléments. De cette façon, vous ne serez pas pénalisé par l'extension pour allonger la liste.

Quelque chose comme:

  private List<ListItem> GetItems()
    {
        var collection = new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
        var items = new List<ListItem>(collection.Count);  //declare the amount of space here

        foreach (var i in collection)
        {
            ListItem item = new ListItem { Text = i.ToString() };
            items.Add(item);
        }

        return items;
    }

Compile probablement dans le même code mais pourquoi se donner la peine de le redéclarer. C'est la bonne chose à propos de la référence, dans ce cas article. Une fois que vous avez terminé, vous pouvez l'assigner à un autre ListItem et au GC. s'occupe du reste.

Mais de l'autre côté, la lisibilité pour les autres programmeurs. C’est une décision qui ne changera certainement pas radicalement les performances de vos applications.

Encore mieux dans votre cas, c'est:

private List<ListItem> GetItems()        
{            
   var items = new List<ListItem>();            
   var collection = new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };            
   foreach (var i in collection)            
      items.Add(new ListItem { Text = i.ToString() });                 
   return items;        
}

Pourquoi créer une variable supplémentaire?

Comme tout le monde l’a spéculé, l’IL sera identique. En outre, comme d'autres l'ont mentionné, ne vous inquiétez pas de ce genre de choses jusqu'à ce que cela devienne un problème. Au lieu de cela, demandez-vous où la portée de cette variable appartient.

La portée et le contexte de ce bloc de code sont beaucoup plus importants que de minuscules optimisations des performances qui seraient prématurées et inutiles dans ce scénario.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top