2009-10-27 12 views
6

Lo que es mejor para un rendimiento inteligente que se declara la variable fuera del DECLARACIÓN foreach y cada vez que se le reasigne en el lado que (foreach) o crear una nueva variable en el interior foreach por ejemploforeach, rendimiento-sabio. ¿Deberíamos declarar la variable una vez antes del ciclo o dentro de él?

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 éste?

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

Seguro aquí hablo sobre el objeto del objeto. gracias a todos.

Respuesta

12

Esto suena como premature optimization.

Antes que nada, ¿tiene alguna razón para creer que hay un problema de rendimiento aquí?

En segundo lugar, en versiones de lanzamiento, el optimizador del compilador probablemente producirá un código idéntico para ambos escenarios, por lo que es probablemente irrelevante. En las compilaciones de depuración esto puede no ser siempre cierto, pero no desea optimizaciones, ya que la intención de las compilaciones de depuración es permitirle avanzar con precisión a través del código.

4

Estoy bastante seguro de que el IL generado por tus dos bloques de código es idéntico. No debería haber ningún cambio en el rendimiento. Sin embargo, el segundo bloque de código donde declaras el tipo de artículo justo donde se usa es un poco más legible y yo usaría eso.

3

Esta es una muy micro-optimización y ambos métodos probablemente serán exactamente los mismos en cuanto a rendimiento, si no generan código idéntico. En este caso, busque legibilidad. Preferiría el segundo, ya que su objeto no sirve para nada fuera del ciclo foreach.

Posiblemente, también puede deshacerse de la referencia almacenada todos juntos:

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

Esto es por lo general lo que hago. Es autosuficiente, así que te votaré por turno: D –

0

compila Probablemente para el mismo código, pero ¿por qué molestarse redeclarandolos ella. Eso es lo bueno de la referencia, en este caso. Una vez que haya terminado con él, puede asignarlo a otro ListItem y el GC se ocupa del resto.

Pero en el otro lado la legibilidad para otros programadores. Es una decisión que ciertamente no cambiará drásticamente el rendimiento de sus aplicaciones.

0

Incluso mejor en su caso es:

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

¿Por qué crear una variable adicional en absoluto?

1

La IL creada por los dos bloques debería ser casi la misma. Si está buscando optimizar, me gustaría fijar la longitud de la lista final antes de llenarla con elementos. De esa forma, no será la penalización de expansión por extender la longitud de la lista.

Algo así como:

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

Como todo el mundo ha especulado, la IL será idéntico. Además, como han mencionado otros, no se preocupe por cosas como esta hasta que se conviertan en un problema. En cambio, pregúntese dónde pertenece el alcance de esa variable.

El alcance y el contexto de ese bloque de código es mucho más importante que las optimizaciones de rendimiento diminutas que serían de naturaleza prematura e innecesarias en este escenario.

7

There es un caso extremo donde esto importa; si "captura" la variable en un método anónimo/lambda. De lo contrario, es prematuro y no hace diferencia. En absoluto.

Un ejemplo de cuando sí importa:

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