Подтвердить что ты не робот

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);
}
4b9b3361

Ответ 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-функции, конечно, - не меняйте параметр-ссылка, если не указано....