2016-04-13 2 views
5

Рассматривая реализацию List.AddRange, я нашел что-то странное, я не понимаю. Sourcecode, see line 727 (AddRange называет InsertRange)Список <T> .AddRange/InsertRange создание временного массива

T[] itemsToInsert = new T[count]; 
c.CopyTo(itemsToInsert, 0); 
itemsToInsert.CopyTo(_items, index); 

Почему это делаешь Скопируйте коллекцию в «ТЕМП-массив» (itemsToInsert) первый и затем копирует временный массив в фактическую _items массива? Есть ли причина в этом, или это просто некоторая проблема с копированием источника ArrayList, потому что там происходит то же самое.

+2

Я бы предположил, что передать элементы через значение вместо ссылки, чтобы исходные элементы, вставленные, не были изменены в случае изменения элементов в списке. –

+1

@Jdsfighter - я не вижу, как это помогает вообще. Содержимое массива или коллекции - это значения или ссылки. Вышеприведенный код ничего не меняет, чем он копируется. –

+0

На самом деле я не думаю, что это скрыть базовый массив. В моем ответе я указал другое вероятное объяснение. – Fabjan

ответ

4

Я предполагаю, что это скрывает существование внутреннего массива поддержки. Невозможно получить ссылку на этот массив, который является преднамеренным. Класс List даже не обещает, что существует такой массив. (Конечно, для производительности и для соображений совместимости он всегда будет реализован с помощью массива.)

Кто-то может передать обработанный ICollection<T>, который запоминает массив, который он передал. Теперь вызывающие абоненты могут взаимодействовать с внутренним массивом List и запускать в зависимости от внутренних компонентов List.

Сравните это с MemoryStream, у которого есть документированный способ доступа к внутреннему буферу (и стрелять в него): GetBuffer().

+0

Если это фактическая причина, то я действительно не вижу смысла: кто-то может также использовать отражение, чтобы искать частные поля массива, если они хотят возиться с вещами. –

+0

Используя отражение, вы можете открыть что-нибудь открытое, но это сложнее и случается реже на практике. Это, по-видимому, защита от случайного или небрежного использования API. Вызывающий код неизменно начинает зависеть от инвариантов, которые сейчас оказываются истинными, но не гарантируются. Чем сложнее это, тем реже оно будет. – usr

+1

Создание коллекции, которая запоминает массивы с намерением возиться с внутренними элементами, не так уж много, я бы сказал. Такое же намерение действительно, а не то, что, на мой взгляд, стоит защищать в библиотеке общего назначения. EDIT: Я вижу, это защищает от некоторых случайных злоупотреблений. Не то, что надуманный, после того, как указано, сколько используется List. –

Смежные вопросы