String.Concat неэффективный код?
Я изучал String.Concat: (Reflector)
![enter image description here]()
очень странно:
имеют массив значений,
они создают NEW ARRAY, для которого позже они отправляют его на ConcatArray
.
Вопрос:
Почему они создали массив new? они имели values
с первого места...
изменить
код:
public static string Concat(params string[] values)
{
if (values == null)
{
throw new ArgumentNullException("values");
}
int totalLength = 0;
string[] strArray = new string[values.Length];
for (int i = 0; i < values.Length; i++)
{
string str = values[i];
strArray[i] = (str == null) ? Empty : str;
totalLength += strArray[i].Length;
if (totalLength < 0)
{
throw new OutOfMemoryException();
}
}
return ConcatArray(strArray, totalLength);
}
Ответы
Ответ 1
Ну, во-первых, это означает, что содержимому нового массива можно доверять не нулевое значение.... и неизменное.
Без этого копирования другой поток может изменить исходный массив во время вызова ConcatArray
, который предположительно может вызвать исключение или даже вызвать ошибку безопасности. При копировании входной массив может быть изменен в любое время - каждый элемент будет считываться ровно один раз, поэтому не может быть несогласованности. (Результатом может быть смесь старых и новых элементов, но вы не получите повреждение памяти.)
Предположим, что ConcatArray
доверено делать массовое копирование из строк в массиве, который он передал, без проверки переполнения буфера. Затем, если вы измените входной массив в нужное время, вы можете записать запись за пределами выделенной памяти. Badness. С этой защитной копией система может быть уверенной 1 что общая длина действительно является общей длиной.
1 Хорошо, если только отражение не используется для изменения содержимого строки. Но это невозможно сделать без достаточно высоких разрешений - в то время как изменение содержимого массива легко.
Ответ 2
Почему они создали новый массив?
Я могу подтвердить гипотезу Джона; У меня исходный исходный код передо мной. Комментарии указывают, что причина для копии заключается в том, что какой-то глупый человек может мутировать массив, который был передан в другой поток. Что может случиться? Расчет длины мог бы сказать, что в результате будет сто байт строковых данных, но к тому моменту, когда произойдет копирование, в массиве может быть миллион байтов строковых данных.
Это было бы плохо. Невозможно легко устранить проблему, сделав копию.
Ответ 3
Они создали новый массив, чтобы нормализовать записи null
в String.Empty
. Это невозможно сделать в предоставленном массиве values
, потому что тогда они будут изменять ввод.
Ответ 4
Неэффективное
Нет, это не имеет значения. Это создание и копирование массива быстро сверкают относительно конкатенации, оно только копирует ссылки.
Похоже, что они делают это, чтобы преобразовать строки null
в входной массив в String.Empty
(они не могут сделать это на values
, потому что он будет изменять вход, который является no no), и обнаруживать конкатенации, которые будут переполняться до фактического выполнения конкатенации (что для теста if(totalLength < 0)
). Кроме того, они могут использовать totalLength
для выделения памяти для конкатенированной строки вверх, что более эффективно.
Ответ 5
Вероятно, чтобы он не менялся в течение всего срока службы метода. Это приведет к тому, что totalLength
не будет больше соответствовать содержимому массива.
Я подозреваю, что ConcatArray
использует некоторое небезопасное копирование памяти и снова не проверяет строку Length
. Можно было бы переписать его, чтобы избежать выделения, но еще одно небольшое, короткоживущее распределение довольно дешево.
Ответ 6
насколько я вижу, они выполняют некоторую работу с этим - угадайте, вы не хотите мутировать исходный... помните, что вы хотите, чтобы ваши строки были неизменными для Concat-функции, конечно, - не меняйте параметр-ссылка, если не указано....