2011-10-25 16 views
15

Cela peut sembler être une mauvaise chose à demander mais pourquoi avons-nous si limite courte du nombre d'objets dans une liste.Limitation de la taille de la liste en C#

i écrit le code suivant pour tester la taille de la liste 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); 
    } 

et la taille de la liste ne pouvait être 134217728

est pas injuste :(??? ce qui est autre façon si je voulez ajouter des objets même au-delà des limites 'entières' (je veux dire le nombre d'objets> 2^32)

+4

Ce n'est pas une machine de Turing, les ordinateurs ont des limites. Quelle est la question? –

+1

vérifier celui-ci: http://stackoverflow.com/questions/3906891/what-is-the-max-limit-of-data-into-liststring-in-c –

+2

que voulez-vous faire avec> 2^32 objets? – stukselbax

Répondre

52

A List<int> est couvert par une int[]. Vous échouerez dès qu'un tableau de sauvegarde plus ne peut être attribuée - et garder à l'esprit que:

  • Il y a une limite de 2 Go par objet dans le CLR même en 64 bits (EDIT: à partir de 4,5 .NET, cette peut être évité pour le CLR 64 bits - voir <gcAllowVeryLargeObjects>)
  • La liste essayera d'allouer une matrice de support qui est plus grande que ce dont elle a besoin immédiatement, afin de répondre aux demandes Add ultérieures sans réaffectation.
  • Lors de la réaffectation, il doit y avoir suffisamment de mémoire totale pour les anciens et nouveaux tableaux.

Réglage de la Capacity à une valeur qui va mettre le tableau de support près de la limite théorique peut vous obtenir un point de coupure supérieure à la croissance naturelle, mais cette limite va certainement venir.

Je attendre une limite d'environ 2 éléments (536,870,912) - Je suis un peu surpris que vous ne l'avez pas réussi à aller au-delà 134.217.728. Combien de mémoire avez-vous réellement? Quelle version de .NET utilisez-vous, et sur quelle architecture? (Il est possible que la limite par objet soit de 1 Go pour un CLR 32 bits, je ne m'en souviens pas.)

Notez que même si la limite par objet n'était pas un problème, dès que vous obtenu au-dessus de 2 éléments que vous auriez des problèmes adressant ces éléments directement avec List<T>, comme l'indexeur prend une valeur int. Fondamentalement, si vous voulez une collection avec plus de int.MaxValue éléments, vous devrez écrire les vôtres, probablement en utilisant plusieurs matrices de sauvegarde. Vous pourriez vouloir interdire explicitement les suppressions et les insertions arbitraires :)

+0

La liste est soutenue par int []? implique que la liste n'est pas une liste, c'est un tableau et l'addition et la suppression dans le tableau est assez coûteuse que la liste, théoriquement. Ai-je raison? (en supposant que 'array soutenu alloué' pourrait être un multiple de la taille de liste actuelle pour éviter trop d'allocation pendant 'Add') Aussi, avec cela dit, quelle est la différence entre List et int [], j'adorerais lire si vous pouvez partager quelques notes internes détaillées. – Umer

+6

@Umer: Les docs le rendent raisonnablement clair: "La classe' List 'est l'équivalent générique de la classe' ArrayList' Elle implémente l'interface générique 'IList ' en utilisant un tableau dont la taille est augmentée dynamiquement si nécessaire. " Quand vous dites que c'est "pas une liste" - cela dépend de ce que vous entendez par "une liste". Ce n'est pas une liste * liée * - si vous en voulez une, vous voulez utiliser 'LinkedList '. La principale différence évidente entre 'List ' et un tableau est qu'un tableau a toujours une taille fixe, alors qu'un 'List ' peut grossir et se rétrécir. –

+2

Cette croissance et ce rétrécissement doivent impliquer une réaffectation appropriée, mais du point de vue de l'API, vous faites toujours face à la même 'List '. –

6

Voici une implémentation incroyablement naïve (et non testée) d'une liste BigList soutenue par un long au lieu d'un entier. Je l'ai écrit dans environ 5 minutes, il ne met pas en œuvre ienumerable ou ilist, b Il montre le Partitionnement qui a été mentionné dans d'autres réponses. oui, il est en VB, faites-le avec :)

Cela nécessitera un travail assez sérieux et un réglage avant qu'il ne soit réellement utilisable, mais cela illustre l'idée.

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 
0

Je ne l'ai pas testé mais en raison de son type de mise en œuvre, le LinkedList<T> devrait vous donner la possibilité d'ajouter plus d'éléments qu'à un List<T>. Mais soyez conscient de ses inconvénients (par exemple appeler Count).

1

limite de liste est ~ 536,870,912 octets (1/2 Mo sur ma machine (32 bits Win7, .NET 4.0))

Vos entiers en ajoutant (4 octets chacun), de sorte que la limite est limite octet/4 (~ 134,217,727)

Questions connexes