elementos - list.count c#
LimitaciĆ³n de tamaƱo de lista en C# (4)
Esto podría parecer algo desagradable, pero ¿por qué tenemos un límite tan corto de cantidad de objetos en una lista?
Escribí el siguiente código para probar el tamaño de la lista en C #
List<int> test = new List<int>();
long test1 = 0;
try
{
while (true)
{
test.Add(1);
test1++;
}
}
catch (Exception ex)
{
MessageBox.Show(test1 + " | " + ex.Message);
}
y el tamaño de la lista solo podría ser 134217728
¿no es eso injusto :(? ¿Cuál es la forma alternativa si quiero agregar objetos incluso más allá de los límites de "enteros" (me refiero al número de objetos> 2 ^ 32)?
Aquí hay una implementación increíblemente ingenua (y no probada) de un BigList respaldado por un Long en lugar de un entero. Lo escribí en aproximadamente 5 minutos, no implementa ienumerable o ilist, pero muestra la partición que se mencionó en otras respuestas. Sí, está en VB, lidiar con eso :)
Esto requerirá un trabajo bastante serio y afinación antes de que sea realmente utilizable, pero ilustra la idea.
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
El límite de la lista es ~ 536,870,912 bytes (1/2 MB en mi máquina (32 bits Win7, .NET 4.0))
Al agregar enteros (4 bytes cada uno), el límite es el byte limit / 4 (~ 134,217,727)
No lo probé, pero debido a su tipo de implementación, la LinkedList<T>
debería darle la posibilidad de agregar más elementos que a una List<T>
. Pero tenga en cuenta sus inconvenientes (por ejemplo, el conteo de llamadas).
Una List<int>
está respaldada por un int[]
. Se producirá un error tan pronto como no se pueda asignar una matriz de respaldo más grande, y tenga en cuenta que:
- Hay un límite de 2GB por objeto en el CLR incluso en 64 bits (EDIT: a partir de .NET 4.5, esto puede evitarse para el CLR de 64 bits - vea
<gcAllowVeryLargeObjects>
) - La lista intentará asignar una matriz de respaldo que sea más grande de lo que requiere inmediatamente, para acomodar más tarde
Add
solicitudes sin reasignación. - Durante la reasignación, tiene que haber suficiente memoria total tanto para la matriz antigua como para la nueva.
Establecer la Capacity
en un valor que coloque la matriz de respaldo cerca del límite teórico puede brindarle un punto de corte más alto que el crecimiento natural, pero ese límite seguramente llegará.
Esperaría un límite de alrededor de 2 29 elementos (536,870,912). Me sorprende un poco que no haya logrado superar los 134,217,728. ¿Cuánta memoria tienes realmente? ¿Qué versión de .NET está utilizando y en qué arquitectura? (Es posible que el límite por objeto sea de 1 GB para un CLR de 32 bits, no puedo recordarlo con seguridad).
Tenga en cuenta que incluso si el límite por objeto no fuera un problema, tan pronto como superara los 2 31 elementos, tendría problemas para tratar esos elementos directamente con la List<T>
, ya que el indexador toma un valor int
.
Básicamente, si desea una colección con más de elementos int.MaxValue
, necesitará escribir la suya, probablemente utilizando múltiples matrices de respaldo. Es posible que desee prohibir explícitamente las eliminaciones y las inserciones arbitrarias :)