String.Concat неэффективный код? - PullRequest
24 голосов
/ 28 марта 2012

Я исследовал String.Concat: (Отражатель)

enter image description here

очень странно:

массив значений,

онисоздание нового массива, для которого позже его отправляют на ConcatArray.

Вопрос:

Почему они создали массив new ?у них было values с первого места ...

edit

код:

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

Ответы [ 6 ]

34 голосов
/ 28 марта 2012

Ну, во-первых, это означает, что содержимое нового массива можно считать ненулевым .... и неизменным.

Без этого копирования другой поток может измените исходный массив во время вызова на ConcatArray, что, вероятно, может вызвать исключение или даже вызвать ошибку безопасности.При копировании входной массив может быть изменен в любое время - каждый элемент будет прочитан ровно один раз, поэтому несоответствия быть не может.(Результат может быть смесью старых и новых элементов, но вы не получите повреждения памяти.)

Предположим, что ConcatArray доверяет массовому копированию строк в переданном массиве.без проверки переполнения буфера.Затем, если вы измените входной массив в нужное время, вы можете закончить запись вне выделенной памяти.Badness.С этой защитной копией система может быть 1 уверена, что общая длина действительно равна общей длине.


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

16 голосов
/ 28 марта 2012

Почему они создали новый массив?

Я могу подтвердить гипотезу Джона; У меня есть исходный код передо мной. В комментариях указывается, что причина копирования в том, что какой-то глупец может поменять массив, который был передан в другой поток . Что тогда может произойти? Расчет длины может сказать, что в результате будет сто байтов строковых данных, но к моменту копирования в массиве может быть миллион байтов строковых данных.

Это было бы плохо. Проблему легко предотвратить, сделав копию.

4 голосов
/ 28 марта 2012

Они создали новый массив для нормализации null записей в String.Empty.Это не может быть сделано в предоставленном массиве values, потому что тогда они будут изменять входные данные.

2 голосов
/ 28 марта 2012

Неэффективно

Нет, это не имеет значения.Создание и копирование массива происходит быстро по сравнению с конкатенацией, это только копирование ссылок.

Похоже, они делают это для преобразования null строк во входном массиве в String.Empty (они не могут сделатьэто на values, потому что это будет модифицировать ввод, который является «нет»), и обнаруживать конкатенации, которые будут переполнены перед тем, как фактически выполнить конкатенацию (это то, для чего предназначен тест if(totalLength < 0)).Кроме того, они могут использовать totalLength для выделения памяти для объединенной строки, что более эффективно.

0 голосов
/ 28 марта 2012

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

0 голосов
/ 28 марта 2012

Вероятно, чтобы убедиться, что это не изменится в течение срока службы метода. Что приведет к тому, что totalLength больше не будет соответствовать содержимому массива.

Я подозреваю, что ConcatArray использует небезопасное копирование памяти и не перепроверяет строку Length s. Можно было бы переписать его, чтобы избежать выделения, но еще одно небольшое, кратковременное распределение довольно дешево.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...