Объявление переменной внутри или вне цикла foreach: что быстрее/лучше?


какой из них быстрее/лучше?

Это:

List<User> list = new List<User>();
User u;

foreach (string s in l)
{
    u = new User();
    u.Name = s;
    list.Add(u);
}

или такой:

List<User> list = new List<User>();

foreach (string s in l)
{
    User u = new User();
    u.Name = s;
    list.Add(u);
}

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

есть ли вообще разница в производительности?

9 72

9 ответов:

С точки зрения производительности оба примера компилируются в один и тот же IL, поэтому нет никакой разницы.

второй лучше, потому что он более четко выражает свои намерения, если u используется только внутри цикла.

в любом случае, лучшим способом будет использовать конструктор, который принимает имя... или, в противном случае, использовать фигурную скобку нотации:

foreach (string s in l)
{
    list.Add(new User(s));
}

или

foreach (string s in l)
{
    list.Add(new User() { Name = s });
}

или даже лучше, LINQ:

var list = l.Select( s => new User { Name = s});

теперь, хотя ваш первый пример может в некоторых случаях быть незаметно быстрее, второй лучше, потому что он более читаем, и компилятор может отбросить переменную (и вообще опустить ее), поскольку она не используется вне foreach's scope.

объявление не вызывает никакого кода для выполнения, так что это не проблема производительности.

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

и кроме того, лучший способ использовать LINQ:

List<User> users = l.Select(name => new User{ Name = name }).ToList();

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

чтобы ответить на ваш вопрос-без измерения : -) или глядя на сгенерированный ilasm - любая разница не будет заметна в значимом количестве итераций и самой дорогой операции в вашем коде, скорее всего, будет распределение пользователей на несколько порядков, поэтому сосредоточьтесь на ясности кода (как вы должны в целом) и идите с ним 2.

о, уже поздно, и я думаю, что я просто пытаюсь сказать, не беспокойтесь о таких вещах или не увлекайтесь такими деталями.

K

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

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

в этом случае вторая версия лучше.

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

не должно быть никакой ощутимой разницы в производительности.