foreach, per quanto riguarda le prestazioni. Dovremmo dichiarare la variabile una volta prima del ciclo o al suo interno?

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

  •  06-07-2019
  •  | 
  •  

Domanda

Cosa c'è di meglio in termini di prestazioni dichiarando la variabile fuori dallo statuto foreach e ogni volta che lo riassegni al suo fianco (foreach) o crei una nuova variabile all'interno di foreach per esempio

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

o questo?

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

sicuro qui parlo di oggetto oggetto. grazie a tutti.

È stato utile?

Soluzione

Sembra un ottimizzazione prematura .

Prima di tutto, hai qualche motivo per credere che ci sia un problema di prestazioni qui?

In secondo luogo, nelle build di rilascio, l'ottimizzatore del compilatore probabilmente produrrà codice identico per entrambi gli scenari , quindi è probabilmente irrilevante. Nelle build di debug questo potrebbe non essere sempre vero, ma lì non si vogliono ottimizzazioni poiché l'intento delle build di debug è di permetterti di scorrere accuratamente il codice.

Altri suggerimenti

C'è c'è un caso limite in cui ciò conta; se " cattura " la variabile in un metodo anonimo / lambda. Altrimenti è prematuro e non fa differenza. Assolutamente.

Un esempio di quando è importante:

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

Sono abbastanza sicuro che l'IL generato dai tuoi due blocchi di codice sia identico. Non dovrebbero esserci cambiamenti nelle prestazioni. Tuttavia, il secondo blocco di codice in cui si dichiara il tipo di elemento nel punto in cui viene utilizzato è leggermente più leggibile e lo userei.

Questa è una micro-ottimizzazione ed entrambi i metodi saranno probabilmente esattamente le stesse prestazioni, se non generando codice identico. In questo caso, vai per leggibilità. Preferirei il secondo, poiché il tuo oggetto non serve a nulla al di fuori del ciclo foreach.

Probabilmente, potresti anche sbarazzarti del riferimento memorizzato tutti insieme:

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 creato dai due blocchi dovrebbe essere quasi lo stesso. Se stai cercando di ottimizzare, vorrei cercare di impostare la lunghezza dell'elenco finale prima di riempirlo con elementi. In questo modo non sarai la penalità di espansione per l'estensione della lunghezza dell'elenco.

Qualcosa del tipo:

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

Probabilmente viene compilato con lo stesso codice, ma perché preoccuparsi di ripeterlo. Questa è la cosa bella del riferimento, in questo caso l'articolo. Una volta terminato, puoi assegnarlo a un altro ListItem e al GC si prende cura di tutto il resto.

Ma d'altra parte leggibilità per altri programmatori. È una decisione che certamente non cambierà drasticamente le prestazioni delle tue applicazioni.

Ancora meglio nel tuo caso è:

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

Perché creare una variabile aggiuntiva?

Come tutti hanno ipotizzato, l'IL sarà identico. Inoltre, come altri hanno già detto, non preoccuparti di cose del genere fino a quando non diventano un problema. Invece, chiediti dove appartiene l'ambito di quella variabile.

L'ambito e il contesto di quel blocco di codice sono molto più importanti delle minuscole ottimizzazioni delle prestazioni che sarebbero di natura prematura e non necessarie in questo scenario.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top