foreach, Performance-weise. Sollten wir Variable deklarieren einmal vor Schleife oder im Inneren?

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

  •  06-07-2019
  •  | 
  •  

Frage

Was ist besser für die Leistung weise die Variable außerhalb des foreach statment erklärt und die jedes Mal in Seiten es (foreach) neu zuweisen oder eine neue Variable in foreach erstellen zum Beispiel

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

oder dieses?

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

Sie sicher, hier bin ich sprechen über Item-Objekt. danke euch allen.

War es hilfreich?

Lösung

Das klingt wie ein vorzeitige Optimierung .

Zunächst einmal haben Sie keinen Grund zu der Annahme haben, dass es ein Performance-Problem ist hier?

Zweitens, in Release-Builds, der Optimierer Compiler wahrscheinlich identischen Code für beide Szenarien erzeugen - so ist es wahrscheinlich irrelevant. Im Debug diese baut nicht immer wahr sein, aber es Sie nicht wollen, Optimierungen, da die Absicht von Debug wird, damit baut man genau durch den Code treten.

Andere Tipps

Es ist ein Rand Fall, in dem diese Fragen; wenn Sie „Capture“ die Variable in eine anonyme Methode / Lambda. Ansonsten ist es verfrüht, und macht keinen Unterschied. Bei allen.

Ein Beispiel, wenn es nicht egal:

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

Ich bin mir ziemlich sicher, dass die IL durch Ihre zwei Codeblöcke erzeugt ist identisch. Es sollte keine Änderung in der Leistung sein. Doch der zweite Codeblock, in dem Sie die Art des Artikel richtig zu erklären, wo es verwendet wird, ist etwas besser lesbar und ich würde diese verwenden.

Dies ist eine sehr-Mikro-Optimierung und beide Methoden werden wahrscheinlich genau die gleiche Performance-weise, wenn nicht identischen Code zu erzeugen. In diesem Fall geht für die Lesbarkeit. Ich würde die zweite bevorzugen, da das Objekt keinen Zweck außerhalb der foreach-Schleife dient.

Argumentieren, können Sie auch alle zusammen von der gespeicherten Referenz loszuwerden:

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

Die IL durch die beiden Blöcke erstellt sollte fast gleich sein. Wenn Sie zu optimieren suchen, würde ich auf die Einstellung der Länge der endgültigen Liste suchen, bevor es mit Gegenständen zu füllen. Auf diese Weise werden Sie nicht die Erweiterung Strafe für die Länge der Liste erstreckt.

So etwas wie:

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

kompiliert Wahrscheinlich auf den gleichen Code aber warum es die Mühe erneut deklariert werden. Das ist das Schöne an der Referenz, in diesem Fall Artikeln. Sobald Sie damit fertig sind, können Sie es an einem anderen ListItem und die GC zuweisen kümmert sich um den Rest.

Aber auf der otherhand Lesbarkeit für andere Programmierer. Es ist eine Entscheidung, die sicherlich nicht drastisch Ihre Anwendungen Leistung ändern.

Noch besser in Ihrem Fall ist:

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

Warum schafft eine zusätzliche Variable überhaupt?

Wie jeder spekuliert hat, wird die IL identisch sein. Auch, wie andere erwähnt haben, keine Sorge über Dinge wie diese, bis sie zu einem Problem werden. Stattdessen fragen Sie sich, wo der Umfang dieser Variablen gehört.

Der Umfang und Rahmen dieses Code-Block ist viel wichtiger als winzige Performance-Optimierungen, die in der Natur und nicht notwendig in diesem Szenario verfrüht wären.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top