foreach, мудрый производительностью. Мы должны объявить переменную однажды цикл или в нем?

// Store the formatted string in 'result'
String result = String.format("%4d", i * j);

// Write the result to standard output
System.out.println( result );

См. формат и синтаксис

6
задан mjv 27 October 2009 в 17:37
поделиться

8 ответов

Звучит как преждевременная оптимизация .

Прежде всего, есть ли у вас какие-либо основания полагать, что здесь есть проблемы с производительностью?

Во-вторых, в сборках релизов оптимизатор компилятора, вероятно, будет производить идентичный код для обоих сценариев , поэтому это, вероятно, не имеет значения. В отладочных сборках это не всегда может быть правдой, но там вам не нужна оптимизация, поскольку цель отладочных сборок - позволить вам точно пошагово выполнять код.

12
ответ дан 8 December 2019 в 03:53
поделиться

Там есть крайний случай, когда это имеет значение; если вы «захватите» переменную анонимным методом / лямбда. В противном случае это преждевременно и без разницы. Вообще.

Пример того, когда это имеет значение:

// 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); });
}
7
ответ дан 8 December 2019 в 03:53
поделиться

Это очень микрооптимизация, и оба метода, скорее всего, будут иметь одинаковую производительность, если не будут генерировать идентичный код. В этом случае стремитесь к удобочитаемости. Я бы предпочел второй вариант, поскольку ваш объект не служит никакой цели за пределами цикла foreach.

Возможно, вы также можете полностью избавиться от сохраненной ссылки:

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;
}
3
ответ дан 8 December 2019 в 03:53
поделиться

Я почти уверен, что IL, сгенерированный вашими двумя блоками кода, идентичен. Никаких изменений в производительности быть не должно. Однако второй блок кода, в котором вы объявляете тип элемента прямо там, где он используется, немного более читабелен, и я бы его использовал.

4
ответ дан 8 December 2019 в 03:53
поделиться

IL, созданный двумя блоками, должен быть почти одинаковым. Если вы хотите оптимизировать, я бы посмотрел на установку длины окончательного списка, прежде чем заполнять его элементами. Таким образом, вы не будете наказаны за расширение списка.

Что-то вроде:

  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;
    }
1
ответ дан 8 December 2019 в 03:53
поделиться

Вероятно, компилируется с тем же кодом, но зачем его повторно объявлять. Это хорошая вещь в ссылке, в данном случае на элементе. Как только вы закончите с ним, вы можете назначить его другому ListItem и GC. обо всем остальном позаботится.

Но с другой стороны, удобочитаемость для других программистов. Это решение, безусловно, не сильно повлияет на производительность ваших приложений.

0
ответ дан 8 December 2019 в 03:53
поделиться

В вашем случае еще лучше:

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
ответ дан 8 December 2019 в 03:53
поделиться

Как все предполагали, IL будет идентичным. Кроме того, как уже упоминали другие, не беспокойтесь о таких вещах, пока они не станут проблемой. Вместо этого спросите себя, где находится область действия этой переменной.

Объем и контекст этого блока кода намного важнее, чем крошечные оптимизации производительности, которые были бы преждевременными по своей природе и ненужными в этом сценарии.

0
ответ дан 8 December 2019 в 03:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: