производительность c # toString()

#c# #.net #tostring

#c# #.net #tostring

Вопрос:

Мне любопытен ToString() метод в C #. Возьмем, к примеру, следующее:

 object height = 10;

string heightStr = height.ToString();
  

Когда я вызываю ToString() on height , я получаю обратно строковый тип. Выделяет ли среда выполнения память для этой строки?

Комментарии:

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

Ответ №1:

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

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

Int32.ToString Метод чрезвычайно быстр. Он обращается к машинному коду, написанному на уровне среды CLR, что вряд ли будет узким местом производительности в любом приложении.

Фактически, реальной проблемой производительности здесь будет боксирование, то есть процесс преобразования типа значения в type object и обратно. Это произойдет потому, что вы объявили height переменную как type object , а затем присвоили ей целочисленное значение.

Гораздо лучше height явно указывать тип int , например, так:

 int height = 10;
string heightStr = height.ToString();
  

Комментарии:

1. Один набор упаковок / распаковок не более неэффективен, чем выделение строки.

2. @Matti: Нет, одного набора может и не быть. Мне нужно было бы посмотреть данные о производительности, чтобы быть уверенным, но здесь это совершенно неуместно. Различие, которое я пытался провести, заключается в том, что боксирование — это то, чего обычно стоит избегать. Это считается «плохой практикой» при написании . ЧИСТЫЙ код, и это, безусловно, то, о чем должен знать каждый. Выделение строк не является проблемой, и этого не следует избегать. Существует гораздо больший потенциал для повторных операций упаковки / распаковки, которые могут вызвать проблемы с производительностью в приложении.

3. В качестве небольшого примечания : блокировка также возникает, если вы вызываете виртуальный метод (такой как toString()) для переменной / выражения типа значения, которое явно не переопределяет его . В случае с int существует явное значение int. toString(), но это не всегда так.

4. Re «для любого объекта string, который вы создаете или запрашиваете», конечно, также существует проблема интернирования — здесь это неприменимо, но «любой» — это большое утверждение

5. Я вынужден не согласиться с вступительным заявлением. Бывают ситуации, когда это может привести к проблемам с производительностью. Если бы это происходило в замкнутом цикле много раз, совокупный эффект распределений мог бы привести к дорогостоящей сборке мусора. В игре очень заметны сборки мусора. В сборщике одного поколения, подобном тому, что используется в compact Framework, вы также рискуете фрагментацией, что приводит к еще большему объему работы для сборщика.

Ответ №2:

ДА. При создании нового экземпляра класса (как в данном случае делается с классом string) для экземпляра будет выделена память.

Комментарии:

1. Я не совсем уверен, какое значение здесь имеет тот факт, что строки являются неизменяемыми. Он не модифицирует существующий экземпляр String класса, а скорее присваивает результат ToString функции переменной, введенной как string . Это приведет к созданию нового экземпляра класса, даже если он не был неизменяемым.

2. @Cody Я упомянул это, чтобы подчеркнуть тот факт, что всем экземплярам string выделяется новый адрес памяти. Вы правы, это не очень актуально, но я подумал, что это может внести некоторую дополнительную ясность. В любом случае, я удалил упоминание о неизменяемости, чтобы избежать путаницы.