Какова максимальная длина массива в .NET в 64-разрядной версии Windows?

Я слышал от кого-то, что максимальный размер массива в .NET составляет 4 ГБ? Просто интересно, правда ли это. Вы бы не мечтали сделать это в 32-битной .NET, но в 64-битной системе с 12 ГБ ОЗУ, может быть, просто, может быть, вы захотите это сделать. :-)


person Keith Hill    schedule 26.02.2010    source источник
comment
Возможно, будущим посетителям этого поста стоит отметить, что .net 4.5 снимает это ограничение, если я правильно его читаю. msdn.microsoft.com/en-us/library /hh285054(v=vs.110).aspx   -  person TravisWhidden    schedule 23.02.2012
comment
@TravisWhidden хорошо, теперь, когда это будущее, я могу сказать, что ограничение все еще существует, к сожалению ...   -  person Thomas Ayoub    schedule 17.06.2015


Ответы (3)


Теоретически массив может содержать не более 2 147 483 647 элементов, поскольку для индексации используется тип int. Фактический предел немного ниже, чем этот, в зависимости от типа, содержащегося в массиве.

Однако в .NET CLR существует ограничение на максимальный размер одного объекта в 2 ГБ, даже в 64-разрядной версии. Это было сделано по дизайну.

Вы можете легко создать реализацию IList<T>, которая внутренне хранит несколько массивов и позволяет вам выйти за пределы ограничения на один объект в 2 ГБ, но в самой структуре его нет.

Однако, как правило, это не является реальной проблемой. В большинстве случаев у вас будут массивы, указывающие на большие классы, поэтому массив просто содержит ссылки. Это означало бы, что ваш массив может эффективно указывать на много-много ГБ памяти, но сам массив не может быть >2 ГБ.


Обратите внимание, что начиная с .NET 4.5 доступен новый параметр, в котором 64-разрядные приложения могут подписаться: gcAllowVeryLargeObjects. С помощью этого нового набора параметров можно получить UInt32.MaxValue (4 294 967 295) элементов в многомерном массиве, хотя одномерный массив по-прежнему ограничен 2 146 435 071 элементом (2 147 483 591 для однобайтовых массивов или массивов структур, не содержащих ничего, кроме байта). ).

Новые правила с этой опцией:

  • Максимальное количество элементов в массиве — UInt32.MaxValue.
  • Максимальный индекс в любом отдельном измерении равен 2 147 483 591 (0x7FFFFFC7) для байтовых массивов и массивов однобайтовых структур и 2 146 435 071 (0X7FEFFFFF) для других типов.
  • Максимальный размер строк и других объектов, не являющихся массивами, не изменился.
person Reed Copsey    schedule 26.02.2010
comment
Не можете ли вы проиндексировать массив с помощью длинного (Int64)? Вы, конечно, можете использовать Array.GetVaue() с длинной, что позволяет гораздо больше элементов, которые все еще могут быть, и массив будет ‹ 2GB, например, в bool[] - person markmnl; 10.11.2010
comment
@Mrk Mnl: Да, вы можете использовать длинную индексацию, но реализация CLR в любом случае не позволяет вам использовать массивы больше, чем индексация int. Массивы в реализации Microsoft .NET всегда ограничены 2 147 483 647 элементами. - person Reed Copsey; 10.11.2010
comment
@Mrk Mnl: Скорее всего, потому что он не совместим с CLS. - person Reed Copsey; 11.11.2010
comment
Глупо, что попытка выделить больший массив вызывает OutOfMemoryException, когда проблема не в реальной памяти. Я думаю, что это должно вызвать исключение MaximumObjectSizeException или что-то подобное. - person Magnus Krisell; 21.04.2012
comment
Хотя на момент написания ответа ответ был правильным, .NET 4.5 снимает это ограничение — см. ответ Марка Гравелла. - person Ian Griffiths; 21.07.2012
comment
@IanGriffiths Это изменяет максимальный РАЗМЕР массива, но по-прежнему имеет максимальные ограничения на количество элементов. Я отредактировал более подробную информацию и обновление для 4.5. - person Reed Copsey; 24.07.2012
comment
Новая функция в .NET 4.5 наиболее интересна, когда тип элемента массива является типом значения размером более 1 байта или ссылочным типом. Например, new ulong[333222111] не вызовет проблем с размером индекса, но превышает лимит в 2 ГБ (поэтому нужен gcAllowVeryLargeObjects). То же самое с new string[333222111] (ссылочный тип). - person Jeppe Stig Nielsen; 18.12.2013
comment
@markmnl Обратите внимание, что в .NET каждый Boolean (bool) в логическом массиве занимает целый байт, а не только 1/8 байта. - person Jeppe Stig Nielsen; 18.12.2013
comment
Как насчет более сложного объекта, такого как DataTable? Это также ограничено 2 ГБ? - person Chris Smith; 24.07.2015
comment
@ReedCopsey Спасибо за поучительную ссылку на дизайн. Является ли LongLength свойство массива вообще полезно? Может быть, на многомерных массивах? - person Louis Somers; 05.12.2015
comment
Массив байтов может иметь максимальный размер Int32.MaxValue - 57. - person Tarik; 02.11.2016
comment
Кстати, описание страницы кажется неверным... new float[2146435071] работает, new float[2146435071 + 1] нет, но максимальный индекс new float[2146435071] равен 2146435070 (и под словом index в массивах Microsoft всегда подразумевает индекс, а не длину, см. различные методы класса Array) - person xanatos; 29.12.2020

В версиях .NET до 4.5 максимальный размер объекта составляет 2 ГБ. Начиная с версии 4.5, вы можете выделять более крупные объекты, если gcAllowVeryLargeObjects включен. Обратите внимание, что ограничение для string не затрагивается, но «массивы» должны охватывать и «списки», поскольку списки поддерживаются массивами.

person Marc Gravell    schedule 26.06.2012
comment
Как это сделать в консольном приложении .net 5? - person Mohamed; 06.05.2021
comment
@Mohamed уверен, что он включен по умолчанию в .NET 6; может быть и в .NET 5 - person Marc Gravell; 06.05.2021

Максимальный размер любого объекта в .NET составляет 2 ГБ.

Это, конечно, накладывает жесткий предел на то, насколько большим вы можете сделать необработанный массив.

Вы можете создать «массив массивов» (и даже создать свой собственный индексатор для доступа к ним, как если бы это был один непрерывный массив) настолько большим, насколько вам нравится, если вы определите для него свой собственный класс.

person Anon.    schedule 26.02.2010
comment
Почему же Microsoft сочла нужным добавить LongLength к объекту массива в .NET 2.0? - person Keith Hill; 26.02.2010
comment
@Keith: я подозреваю, что это было сделано для проверки на будущее, хотя на самом деле его нельзя использовать каким-либо значимым образом в текущих реализациях CLR (включая CLR 4). - person Reed Copsey; 26.02.2010
comment
@Keith: Почему Microsoft добавила LongLength? - Я предполагаю, что это связано с тем, что ограничение размера объекта в 2 ГБ является деталью реализации, а не ограничением по контракту. Возможно также, что в какой-то момент они планировали увеличить лимит, но обнаружили, что преимущества не стоят проблем, с которыми они столкнулись (или что-то в этом роде). - person Michael Burr; 26.02.2010
comment
Начиная с .NET 4.5, LongLength теперь полезен - см. ответ Марка Гравелла. - person Ian Griffiths; 21.07.2012
comment
Этот ответ следует удалить, он просто больше недействителен - person Chris Marisic; 28.04.2015