foreach, em termos de performance. Devemos declarar variável uma vez antes de loop ou dentro dela?

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

  •  06-07-2019
  •  | 
  •  

Pergunta

O que é melhor para o desempenho sábio declarar a variável fora do statment foreach e cada vez que transferir-lo no lado dele (foreach) ou criar uma nova variável dentro foreach por exemplo

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 este?

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

Certifique-se aqui eu sou falar objeto item. obrigado a todos.

Foi útil?

Solução

isso soa como um prematura otimização .

Em primeiro lugar, você tem alguma razão para acreditar que há um problema de desempenho aqui?

Em segundo lugar, em compilações, otimizador do compilador irá provavelmente produzir código idêntico para ambos os cenários - por isso é provável irrelevante. Em compilações de depuração isso pode não ser sempre verdade, mas há que você não quer otimizações desde a intenção de compilações de depuração é para permitir que você precisa passo através do código.

Outras dicas

Não é um caso extremo, onde isso é importante; se você "capturar" a variável em um método anônimo / lambda. Caso contrário, é prematuro e não faz diferença. Em tudo.

Um exemplo de quando isso 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); });
}

Eu tenho certeza que a IL gerado por seus dois blocos de código é idêntico. Não deve haver qualquer alteração no desempenho. No entanto, o segundo bloco de código onde você declarar o tipo de certo ponto onde ele é usado é um pouco mais legível e gostaria de usá-lo.

Este é um muito-micro-otimização e ambos os métodos provavelmente será exatamente o mesmo em termos de performance, se não gerar o código idêntico. Neste caso, vá para facilitar a leitura. Eu prefiro a segunda, desde que seu objeto não serve para nada fora propósito do loop foreach.

Provavelmente, você também pode se livrar da referência armazenados 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;
}

A IL criada pelos dois blocos deve ser quase o mesmo. Se você está procurando para otimizar, eu olhava para definir o comprimento da lista final antes de o encher com itens. Dessa forma, você não vai ser a pena de expansão para estender o comprimento da lista.

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

Provavelmente compila para o mesmo código, mas por que se preocupar redeclaring-lo. Essa é a coisa agradável sobre a referência, neste item caso. Depois que você fez com ele você pode atribuí-lo a outro ListItem eo GC cuida do resto.

Mas na legibilidade otherhand para outros programadores. É uma decisão que certamente não irá mudar drasticamente o seu desempenho aplicações.

Mesmo melhor no seu 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;        
}

Por que criar uma variável extra em tudo?

Como todos especularam, a IL serão idênticos. Além disso, como já foi mencionado, não se preocupe com coisas como esta até que se tornem um problema. Em vez disso, pergunte a si mesmo onde o escopo dessa variável pertence.

O escopo eo contexto desse bloco de código é muito mais importante do que pequenas otimizações de desempenho que seria prematuro na natureza e desnecessário neste cenário.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top