С # эквивалент вектора С ++ с непрерывной памятью?

87

Что такое C # эквивалент вектора C ++?

Я ищу эту функцию:

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

Я искал и они говорят .NET equivalent to the vector in C++ is the ArrayList так:

Есть ли у ArrayList функция непрерывной памяти?

Эдгармце
источник
4
Разве среда CLR не настолько близка к металлической, чтобы вы могли указать (или даже постоянно ожидать), как структура размещается в памяти?
Aphex

Ответы:

104

Вы можете использовать, List<T>и когда Tэто тип значения, он будет выделен в непрерывной памяти, чего не было бы, если бы Tэто был ссылочный тип.

Пример:

List<int> integers = new List<int>();
integers.Add(1);
integers.Add(4);
integers.Add(7);

int someElement = integers[1];
Дарин Димитров
источник
2
@cMinor, документация List<T>класса содержит много примеров, но я обновил свой ответ, включив один.
Дарин Димитров
5
Я не на 100% знаком с CLR, но имеет смысл, что даже если Tэто ссылочный тип, у вас все равно будет непрерывная память. По сути, это массив указателей ...
josaphatv
«чего бы не было, если бы T был ссылочным типом» - это так же верно, как и для T[]... OP запросил «отсутствие снижения производительности для доступа по сравнению со стандартными массивами» и List<T>предоставляет это. И если Tэто ссылочный тип, он аналогичен типу T*C ++, поэтому вы получаете такую ​​же непрерывность, как и в C ++. Если кто-то хочет, чтобы сами объекты были смежными, тогда, конечно, нужны типы значений ... на обоих языках. Разница, конечно же, в том, что в C ++ любой тип может использоваться как значение или ссылка, тогда как в C # это свойство типа через различие между классом и структурой.
Джим Балтер
Узнал кое-что сегодня. Я думал, List<T>что всегда реализован как связанный список внутри. Так как же тогда он динамически расширяется, когда мы звоним Add()? Что-то вроде VB6, Redim Preserveкоторый раньше копировал весь массив в новое место?
dotNET 07
@dotNet внутри List<T>создает небольшой массив T[]. Внутренние элементы добавляются в массив. Как только размер массива завершен, создается новый массив вдвое больше предыдущего. Данные копируются в новый больший массив, меньший уничтожается и так далее. Разработчик может дать намек на .NET , чтобы создать достаточно большой внутренний массив перед заполнением с List помощью конструктора: new List<T>(expected_array_size).
Artru
16

использовать List<T>. Внутри он использует массивы, а массивы используют непрерывную память.

Бала Р
источник
2
Не совсем так. Если T является ссылочным типом, непрерывной памяти не будет.
Маттео Моска,
2
@Matteo, если вы посмотрите на источник, он private T[] _items;используется для внутреннего хранилища, ссылочного типа или нет.
Bala R
13
Я знаю это. Но скажи мне. У вас есть List <SomeClass>. Ссылки на экземпляры SomeClass будут храниться в непрерывной памяти, но не сами экземпляры. В качестве ссылочных типов они будут находиться в куче, и вы наверняка знаете, как работает куча.
Маттео Моска,
@MatteoMosca, хранящая ссылки непрерывно, по крайней мере, устраняет один уровень косвенности. Думаю, лучше, чем ничего.
Тим Сегин
7
@MatteoMosca OP попросил «без потери производительности для доступа по сравнению со стандартными массивами». Это верно для List <T> независимо от того, что такое T, поэтому все ваши комментарии на этой странице неуместны.
Джим Балтер,
16

Прежде всего, держитесь подальше от Arraylist или Hashtable. Эти классы следует считать устаревшими в пользу универсальных. Они по-прежнему используются в языке для устаревших целей.

Теперь то, что вы ищете, - это List<T>класс. Обратите внимание, что если T - тип значения, у вас будет непрерывная память, но не если T - ссылочный тип, по очевидным причинам.

Маттео Моска
источник
15

В C # много ссылочных типов. Даже если в контейнере ссылки хранятся непрерывно, сами объекты могут быть разбросаны по куче.

Армен Цирунян
источник