Это лучше кодирует практику для определения переменных вне foreach даже при том, что более подробный?

В следующих примерах:

  • первое кажется более подробным, но менее расточительным из ресурсов
  • второе является менее подробным, но более расточительным из ресурсов (переопределяет, представляют каждый цикл в виде строки),

Который лучше кодирует практику?

Первый пример:

using System;
using System.Collections.Generic;

namespace TestForeach23434
{
    class Program
    {
        static void Main(string[] args)
        {
            List<string> names = new List<string> { "one", "two", "two", "three", "four", "four" };

            string test1 = "";
            string test2 = "";
            string test3 = "";
            foreach (var name in names)
            {
                test1 = name + "1";
                test2 = name + "2";
                test3 = name + "3";
                Console.WriteLine("{0}, {1}, {2}", test1, test2, test3);
            }
            Console.ReadLine();
        }
    }
}

Второй пример:

using System;
using System.Collections.Generic;

namespace TestForeach23434
{
    class Program
    {
        static void Main(string[] args)
        {
            List<string> names = new List<string> { "one", "two", "two", "three", "four", "four" };

            foreach (var name in names)
            {
                string test1 = name + "1";
                string test2 = name + "2";
                string test3 = name + "3";
                Console.WriteLine("{0}, {1}, {2}", test1, test2, test3);
            }
            Console.ReadLine();
        }
    }
}
23
задан Edward Tanguay 5 March 2010 в 17:23
поделиться

11 ответов

Вторая форма не более расточительна - она ​​просто лучше.

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

(Обратите внимание, что обычно это не влияет на поведение, но это неверно, если переменные захватываются лямбда-выражением или анонимным методом.)

45
ответ дан 29 November 2019 в 00:56
поделиться

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

1
ответ дан 29 November 2019 в 00:56
поделиться

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

0
ответ дан 29 November 2019 в 00:56
поделиться

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

0
ответ дан 29 November 2019 в 00:56
поделиться

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

Это дает много преимуществ:

  1. Это проще для рефакторинга, поскольку извлечение метода проще, когда переменные уже находятся в одной области видимости.
  2. Использование переменных более понятно, что приведет к более надежному коду.

Единственным (потенциальным) недостатком может быть дополнительное объявление переменных - однако JIT имеет тенденцию оптимизировать этот вопрос, так что в реальной работе я бы не стал беспокоиться об этом.

Единственное исключение из этого:

Если ваша переменная будет оказывать большое давление на GC, и если этого можно избежать повторным использованием одного и того же экземпляра объекта в цикле foreach/for, и если давление GC вызывает измеренные проблемы с производительностью, я бы перенес ее во внешнюю область видимости.

18
ответ дан 29 November 2019 в 00:56
поделиться

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

Моя собственная философия в этом вопросе проста:

Оптимизировать для простоты понимания.

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

2
ответ дан 29 November 2019 в 00:56
поделиться

Это и расточительно, и многословно.

foreach (var name in names)
{
   Console.WriteLine("{0}1, {0}2, {0}3", name);
}

.

</tongueincheek>
5
ответ дан 29 November 2019 в 00:56
поделиться

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

0
ответ дан 29 November 2019 в 00:56
поделиться

Следуйте простому правилу при объявлении переменных

Объявляйте их, когда они нужны в первый раз

-1
ответ дан 29 November 2019 в 00:56
поделиться

Для данных типа POD объявляются наиболее близкие к первому использованию. Для чего-либо, подобного классу, который выполняет какое-либо выделение памяти, вам следует рассмотреть возможность объявления их вне каких-либо циклов. Строки почти наверняка будут выполнять некоторую форму распределения, и большинство реализаций (по крайней мере, на C ++) будут пытаться повторно использовать память, если это возможно. Распределение на основе кучи действительно может быть очень медленным.

Однажды я профилировал фрагмент кода C ++, который включал в свой ctor класс, который обновлял данные. С переменной, объявленной вне цикла, он работал на 17% быстрее, чем с переменной, объявленной внутри цикла. YMMV в C #, так что производительность профиля вы можете быть очень удивлены результатами.

0
ответ дан 29 November 2019 в 00:56
поделиться

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

Может быть, вы можете опубликовать реальную проблему вместо примера?

0
ответ дан 29 November 2019 в 00:56
поделиться
Другие вопросы по тегам:

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