2011-10-25 21 views
15

Może to wydawać się brzydką rzeczą, aby zapytać , ale dlaczego mamy tak krótki limit liczby obiektów na liście.Ograniczenie rozmiaru listy w C#

Napisałem następujący kod do testowania rozmiaru listy w języku 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); 
    } 

i rozmiar listy może być tylko 134217728

nie jest to niesprawiedliwe :(??? co to alternatywny sposób, jeśli ja chce dodawać obiekty nawet poza limity "całkowite" (mam na myśli liczbę obiektów> 2^32)?

+4

To nie jest maszyna Turinga, komputery mają ograniczenia. Jakie jest pytanie? –

+1

sprawdź ten: http://stackoverflow.com/questions/3906891/what-is-the-max-limit-of-data-into-list-in-c-pl –

+2

co chcesz zrobić z> 2^32 obiekty? – stukselbax

Odpowiedz

52

List<int> jest wspierany przez int[]. będzie nie tak szybko, jak większa tablica podłoże nie może być przydzielona - i pamiętać, że:

  • Istnieje limit 2GB na obiekt w CLR nawet w 64 bity (EDIT: jak .NET 4.5, to można tego uniknąć dla 64-bitowego CLR - patrz <gcAllowVeryLargeObjects>)
  • Lista spróbuje przydzielić tablicę backingową, która jest większa niż wymagana od razu, w celu dostosowania późniejszych żądań Add bez realokacji.
  • Podczas realokacji musi być wystarczająca ilość pamięci całkowitej dla obu nowych tablic i.

Ustawianie Capacity do wartości, która będzie umieścić tablicę podkładową pobliżu granicy teoretycznej może Ci wyższą temperaturę graniczną niż przyrostu naturalnego, ale to ograniczenie z pewnością nadejdzie.

bym oczekiwać granicę około 2 elementów (536,870,912) - Jestem nieco zaskoczony, że nie udało się wyjść poza 134,217,728. Ile masz pamięci? Jakiej wersji .NET używasz i na jakiej architekturze? (Możliwe, że limit dla jednego obiektu wynosi 1 GB dla 32-bitowego CLR, nie pamiętam na pewno.)

Należy pamiętać, że nawet jeśli limit na obiekt nie był problemem, tak szybko jak tylko Powyżej 2 elementów, które mogą mieć problemy adresowania tych elementów bezpośrednio z List<T>, jak indeksator ma wartość int.

Zasadniczo, jeśli chcesz kolekcję zawierającą więcej niż int.MaxValue elementów, musisz napisać własną, prawdopodobnie za pomocą wielu tablic tylnych. Możesz wyraźnie zabronić przeprowadzek i dowolnych wstawień :)

+0

Lista jest wspierana przez int []? sugeruje, że lista nie jest listą, jej tablica i dodanie oraz usunięcie w tablicy jest dość kosztowne niż lista, teoretycznie. Czy mam rację? (przy założeniu, że "przydzielona tablica z zabezpieczeniami" może być pewną wielokrotnością bieżącego rozmiaru listy, aby uniknąć zbyt wielu przydziałów podczas "Dodaj") Ponadto, z tą różnicą, że jest różnica między listą a int [], z przyjemnością przeczytam jeśli możesz podzielić się szczegółowymi notatkami wewnętrznymi. – Umer

+6

@Umer: Dokumenty wyjaśniają wyraźnie: "Klasa' List 'jest generycznym odpowiednikiem klasy' ArrayList' i implementuje ogólny interfejs 'IList ', wykorzystujący tablicę, której rozmiar jest dynamicznie zwiększany zgodnie z wymaganiami." Kiedy mówisz, że to "nie jest lista" - to zależy od tego, co masz na myśli przez "listę". To nie jest lista * połączonych * - jeśli chcesz jedną z nich, chcesz użyć 'LinkedList '. Podstawową oczywistą różnicą między 'List ' a tablicą jest to, że tablica ma zawsze stały rozmiar, podczas gdy 'List ' może rosnąć i kurczyć się. –

+2

To rosnące i kurczące się musi odpowiednio obejmować realokację, ale z punktu widzenia API wciąż mamy do czynienia z tym samym 'Listem '. –

6

Oto niesamowicie naiwna (i nietestowana) implementacja BigList wspieranej przez Long zamiast liczby całkowitej. Napisałem to w około 5 minut, nie zaimplementowałem niezliczonej ilii, b ut to pokazuje partycjonowanie, o którym wspominano w innych odpowiedziach. tak, to w VB, radzę sobie z tym :)

Będzie to wymagało dość poważnej pracy i dostrojenia, zanim będzie w rzeczywistości możliwe do wykorzystania, ale ilustruje ideę.

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

Nie przetestowałem tego, ale ze względu na jego implementację LinkedList<T> powinien dać Ci możliwość dodania większej ilości elementów niż do List<T>. Ale pamiętaj o jego wadach (np. Liczba połączeń).

1

granica Lista jest ~ 536,870,912 bajtów (1/2 MB na moim komputerze (Win7 32 bit, .NET 4.0))

Twoje dodawanie liczb całkowitych (4 bajtów każdy), więc granica to granica bajt/4 (~ 134,217,727)

Powiązane problemy