Лучшая практика создания объектов, используемых для циклов for/foreach
Какая наилучшая практика для работы с объектами для циклов foreach или foreach? Должны ли мы создать один объект за пределами циклов и воссоздать его снова (используя новый...) или создать новый для каждой итерации цикла?
Пример:
foreach(var a in collection)
{
SomeClass sc = new SomeClass();
sc.id = a;
sc.Insert();
}
или
SomeClass sc = null;
foreach(var a in collection)
{
sc = new SomeClass();
sc.id = a;
sc.Insert();
}
Что лучше?
Ответы
Ответ 1
Первый способ лучше, поскольку он более четко передает предполагаемую область действия переменной и предотвращает случайные ошибки при использовании объекта вне предполагаемой области действия.
Одна из причин желания использовать вторую форму - это если вы хотите выйти из цикла и все еще иметь ссылку на объект, который вы последний раз достигли в цикле.
Плохая причина выбора второй формы - это производительность. На первый взгляд может показаться, что второй метод использует меньше ресурсов или что вы только создаете один объект и повторно используете его. Здесь не так. Повторное объявление переменной внутри цикла не потребляет дополнительных ресурсов или тактовых циклов, поэтому вы не получаете какой-либо выгоды от вытягивания декларации вне цикла.
Ответ 2
Во-первых, я отмечаю, что вы имеете в виду "создание переменных", когда вы говорите "создание объектов". Ссылки на объекты идут в переменных, но они не являются самими переменными.
Обратите внимание, что описанный сценарий вводит смысловую разницу, когда цикл содержит анонимную функцию, а переменная является замкнутой внешней разновидностью анонимной функции. См
http://ericlippert.com/2009/11/12/closing-over-the-loop-variable-considered-harmful-part-one/
для деталей.
Ответ 3
Я уверен, что кто-то может вытолкнуть анализ MSIL, но практически нет заметной разницы в исполнении или производительности. Единственное, что вы затрагиваете, это хранение ссылки на объект.
Я говорю, держите его чистым и простым; объявить переменную внутри цикла. Это обеспечивает принцип открытого/закрытого на практике, поэтому вы знаете область применения переменной и не используются повторно в других местах. В следующем цикле переменная теряет область действия и автоматически инициализируется.
Ответ 4
Вы создаете новый объект в каждой итерации цикла в обоих случаях (так как вы вызываете new SomeClass()
).
В предыдущем подходе ясно, что sc
используется только внутри цикла, что может быть преимуществом с точки зрения обслуживания.
Ответ 5
Я думаю, что это не важно для производительности, но я предпочитаю первую. Я всегда стараюсь, если возможно, вместе декларировать и создавать экземпляры.
Ответ 6
Я бы пошел с опцией 2, чтобы быть аккуратным, чтобы сохранить все объявления в одном месте.
Вы можете сказать, что
"объекты должны быть объявлены только там, где и когда они нужны"
но ваша петля, вероятно, будет иметь собственный небольшой метод.
Ответ 7
Я бы использовал первый, но для компилятора это то же самое, потому что компилятор вытесняет объявление переменных из циклов. Уверен, что после компиляции код будет выглядеть как второй.