Что предпочесть: int x = arr.Lenth + strText.Append(x) или strText.Append(arr.Lenth)?

Рейтинг: 3Ответов: 3Опубликовано: 23.04.2015

Что предпочесть для вывода длины массива:

передать в переменную int x = arr.Lenth, и уже потом сделать strText.Append(x);

или обойтись без промежуточных этапов: strText.Append(arr.Lenth);


Проблема, если правильно понимаю, связана с уничтожением объектов сборщиком мусора. В первом случае в памяти останется только переменная х, во-втором - до момента вывода arr.Length массив будет находится в памяти. Или нет?

Ответы

▲ 4Принят

Вы бы сперва обозначили скоупы, в которых у вас находятся arr и вызов strText.Append().


Предположим, они находятся внутри одно скоупа.

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

Время сборки объектов недетерминировано и зависит от реализации CLR

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

void Foo()
{
    int arr = new int[5];
    int x = arr.Length;    
    // какой-то длинный код
    strText.Append(x); // в этом месте память из-под arr еще может быть не освобождена!
}

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


Если переменные arr и вызов strText.Append() находятся в разных скоупах, время между заполнением массива и вызовом метода сильно неопределенное и на момент вызова метода массив уже давно не нужен, тогда сохранение длины массива тоже теоретически имеет смысл. Чуть больший, чем в первом случае :).


Почему теоретически? Во всех рассуждения об оптимизациях нужно руководствоваться только практикой. Как говорил классик: "Преждевременная оптимизация -- корень всех зол". Поэтому подобные вещи стоит принимать во внимание только когда "припрет": приложение начнет потреблять много памяти, процесс начнет много времени проводить в GC и т.д. Вот тогда берем в руки профайлер, смотрим на неоптимальные участки кода и вносим исправления. А до тех пор подобные вопросы имеют чисто теоретическую направленность.

▲ 4

1) На всех семинарах по C# неоднократно говорилось, что код вида:

   int x = 3;
   int y = x * 2;

оптимизатором превращается в код

 int y = 3 * 2;

выбрасывая х вообще.

2) Давайте подумаем логически. Код

int x = arr.Length;    
// какой-то длинный код, очень, очень, очень длинный код, на 1 500 000 строк
strText.Append(x);

зачем оптимизатору держать в памяти, все 1 500 000 строк кода, переменную х? Если он это может вычислить в нужной точке

strText.Append(arr.Length);

Вариант, когда внутри этих 1 500 000 строчек кода меняется длина arr не рассматривается, потому-что хранение переменной x тогда вообще не имеет смысла.

3) Конструкция типа

 int x = arr.Length;    
// какой-то длинный код
strText.Append(x);

имеет право быть, в режиме Debug если Вам нужно посмотреть что происходит с длиной массива (х). В режиме Release оптимизатор ее выбросит (х).

P.S. А чего Вы так боитесь сборщика мусора? У меня была прога, которая обрабатывала 90 000 000 записей базы и работала всю ночь каждый день. И ни разу сборщик ничего нужного не удалил...

▲ 2

передать в переменную int x = arr.Lenth, и уже потом сделать strText.Append(x);

Это имеет смысл делать только если

  • массив достаточно большой (не пару тысяч элементов, а действительно большой).
  • есть код код между int x = arr.Lenth и strText.Append(x); который выполняется достаточно долго (не пол секунды, а действительно долго).

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