Ограничение размера списка в С#

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

Я написал следующий код для проверки размера списка в С#

    List<int> test = new List<int>();            
    long test1 = 0;
    try
    {
        while (true)
        {
            test.Add(1);
            test1++;
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show(test1 + "   |   " + ex.Message);
    }

и размер списка может быть только 134217728

не так несправедливо:( Что альтернативный путь, если я хочу добавить объекты даже за пределы "целочисленные" (я имею в виду количество объектов > 2 ^ 32)???

Ответы

Ответ 1

A List<int> поддерживается int[]. Вы потерпите неудачу, как только больший массив поддержки не может быть выделен - и имейте в виду, что:

  • В CLR существует ограничение на 2 ГБ в 64 бит (EDIT: с .NET 4.5 этого можно избежать для 64-битного CLR - см. <gcAllowVeryLargeObjects>)
  • В списке будет предложено выделить массив поддержки, который больше, чем он требует от него, чтобы разместить последующие запросы Add без перераспределения.
  • Во время перераспределения должно быть достаточно полной памяти как для старого, так и для нового массива.

Установка Capacity значения, которое поставит задний массив вблизи теоретического предела, может привести к более высокой точке отсечки, чем естественная роста, но этот предел обязательно придет.

Я ожидал бы предела около 2 29 элементов (536 870 912) - я немного удивлен, что вам не удалось преодолеть 134 217 728. Сколько памяти у вас на самом деле? Какую версию .NET вы используете и какую архитектуру? (Возможно, что ограничение по каждому объекту составляет 1 ГБ для 32-битного CLR, я точно не помню.)

Обратите внимание, что даже если ограничение по каждому объекту не было проблемой, как только вы получили выше 2 31 у вас возникнут проблемы с этими элементами непосредственно с List<T>, так как indexer принимает значение int.

В принципе, если вам нужна коллекция с более чем int.MaxValue элементами, вам нужно будет написать свой собственный, возможно, используя несколько массивов поддержки. Вы можете явно запретить удаление и произвольные вставки:)

Ответ 2

Вот невероятно наивная (и непроверенная) реализация BigList при поддержке Long, а не целого. Я написал его примерно через 5 минут, он не реализует ienumerable или ilist, но показывает Partitioning, о котором упоминалось в других ответах. да, это в VB, справитесь с этим:)

Это потребует довольно серьезной работы и настройки до того, как она будет использоваться, но иллюстрирует эту идею.

Public Class BigList(Of T)
    Private mInternalLists As List(Of List(Of T))
    Private mPartitionSize As Integer = 1000000

    Private mSize As Long = 0

    Public Sub New()
        mInternalLists = New List(Of List(Of T))
    End Sub

    Public Sub Add(Item As T)
        mSize += 1

        Dim PartitionIndex As Integer = CInt(mSize \ mPartitionSize)

        Dim Partition As List(Of T)
        If mInternalLists.Count < PartitionIndex Then
            Partition = New List(Of T)
            mInternalLists.Add(Partition)
        Else
            Partition = mInternalLists(PartitionIndex)
        End If
        Partition.Add(Item)
    End Sub

    Default Public ReadOnly Property Item(Index As Long) As T
        Get
            Dim PartitionIndex As Integer = CInt(mSize \ mPartitionSize)
            Dim Partition As List(Of T)
            If mInternalLists.Count < PartitionIndex Then
                Throw New IndexOutOfRangeException
            Else
                Partition = mInternalLists(PartitionIndex)
            End If

            Return Partition(CInt(mSize Mod mPartitionSize))
        End Get
    End Property
End Class

Ответ 3

Лимит списков ~ 536 870 912 байтов (1/2 МБ на моей машине (32 бит Win7,.NET 4.0))

Ваши целые числа (по 4 байта), поэтому ограничение ограничено байтом /4 (~ 134 217 727)

Ответ 4

Я не тестировал его, но из-за его реализации LinkedList<T> должен дать вам возможность добавить больше элементов, чем a List<T>. Но имейте в виду недостатки (например, вызов Count).