70

What is the default capacity of a List?

Dariusz Woźniak
  • 9,640
  • 6
  • 60
  • 73
Jawahar BABU
  • 1,055
  • 2
  • 9
  • 7
  • 9
    Depending on the default capacity is, in my opinion, a bug. Just use the constructor that takes the initial capacity as parameter, and you definitely know the capacity. – OregonGhost Nov 19 '09 at 12:11
  • 3
    Definitely not a bug if you know, how the List works, and it's high probability the list will be empty, or contain less than 4 elements. – Harry Jul 31 '15 at 07:45
  • Based on Thorarin's answer: https://dotnetfiddle.net/OoRIHl – Daniel B Feb 06 '18 at 17:17
  • 1
    https://referencesource.microsoft.com/#mscorlib/system/collections/generic/list.cs,38 – David Klempfner Dec 07 '19 at 06:17

7 Answers7

69

Actually, it starts with a Capacity of 0. When you add the first element, the current implementation allocates a capacity of 4. After that, the capacity keeps doubling if expansion is needed, to guarantee amortized O(1) operation.

Keep in mind that this is the current behavior. You shouldn't rely on it to be the case. This should demonstrate the current behavior:

List<int> list = new List<int>();
int capacity = list.Capacity;
Console.WriteLine("Capacity: " + capacity);

for (int i = 0; i < 100000; i++)
{
    list.Add(i);
    if (list.Capacity > capacity)
    {
        capacity = list.Capacity;
        Console.WriteLine("Capacity: " + capacity);
    }
}
Thorarin
  • 47,289
  • 11
  • 75
  • 111
  • Could you expand on what you mean by "to guarantee amortized O(1) operation"? – David Klempfner Dec 07 '19 at 06:18
  • Basically be means that no matter how much capacity you need.. the more – Matthew Czarnek Dec 10 '19 at 22:38
  • 1
    @DavidKlempfner if you double capacity every time, you'll be allocating space for roughly `2n` items (including past allocations) - so since that's for `n` `.Add`s, it comes out to roughly `2` arbitrary units of time per `.Add`, aka amortized `O(1)` time. (of course, this assumes allocation takes linear time) – somebody Feb 21 '22 at 09:38
62

Why don't you just try it?

Console.WriteLine("Default capacity of a List: " + new List<int>().Capacity);

This answer will work on all versions of .NET that have List. On my version, it happens to be 0.

Mark Byers
  • 811,555
  • 193
  • 1,581
  • 1,452
  • 5
    The "Why don't you just try it?" question puts the question in a negative light, which is a mistake IMHO. There should be questions here even for things that "are easily tried" for documentation purposes. – julealgon Sep 01 '21 at 19:26
52

According to the sample on the MSDN parameterless constructor documentation, the initial capacity of a list created with:

List<string> x = new List<string>();

is 0. As far as I can tell, this isn't documented as a guarantee, nor is the resize policy documented (i.e. it may currently double with a minimum of 4, but in .NET 5.0 it could triple with a minimum of 128.) You shouldn't rely on this behaviour, basically.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Actually it states that it "is empty and has the default initial capacity". Using Reflector the default is revealed as 4. – Brian Rasmussen Nov 19 '09 at 12:10
  • 11
    @Brian: Nope, the default initial capacity is 0 in this case. 4 is the first capacity for a list which has to have elements. The important thing is that it's *not documented* to be either 0 or 4. It could be 100 in the next version without breaking any documented behaviour. – Jon Skeet Nov 19 '09 at 12:13
  • 1
    @Brian: Whatever the documentation says, it starts with 0 according to the `Capacity` property. – Thorarin Nov 19 '09 at 12:14
  • 2
    @Jon: I completely agree that this is an implementation detail, which is the important point here. And I see your point. 4 is the "default capacity" once something is actually added to the list. – Brian Rasmussen Nov 19 '09 at 12:29
7

The default capacity of List is 4 items (after you insert an initial item, otherwise it's of 0 size)

var list = new List<int>();
list.Add(1);

Assert.AreEqual(4, list.Capacity);
Elisha
  • 23,310
  • 6
  • 60
  • 75
  • Yes, it grows exponentially like that, 4, 8, 16, 32, 64... but default is definitely 0. – David Hedlund Nov 19 '09 at 12:07
  • 8
    Note that it keeps doubling the initial capacity, not necessarily powers of 2. If you give an initial capacity of 3 then you'll get 3, 6, 12, 24, etc. – yoyo Mar 18 '14 at 05:55
  • 1
    So the default capacity is 0, not four. Following your logic "default" capacity is 1 million (after inserting a few thousands items for a good start). – greenoldman Dec 09 '18 at 08:54
3

The capacity default is 0, but if you create a blank list [List1] as below. If the list you created has elements in [List2] as follows, the number of the elements you add becomes N over 2. The default capacity varies.

List<int> List1 = new List<int>(); //count=0, capacity=0
List<int> List2 = new List<int>(){ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; //count=11, capacity=16

When the elements of Array type were added, the developers expanded the array with the ReSize method. It worked very slowly. While developing the List type, the capacity was increased to a certain extent. This ratio has been developed as N above 2.

If more than the number of members are added to the list, the current capacity is doubled. Capacity will not decrease if you delete some values from the list. Capacity only increases, not decreases. Even the Clear method does not affect it.

Fatih GÜRDAL
  • 1,489
  • 1
  • 17
  • 19
  • Thought the default was 4 or 8? Not 0? At zero you should surely be resizing 0*2 which is not going to work. – WDUK Apr 18 '22 at 08:34
1

Capacity should be used if you know roughly how many items you want to store in List (or in Stack, or Queue).

In this case you will avoid memory copying. The memory copying happens because under the hood Lists (Stacks and Queues) rely on array to store their items. That array size is you capacity, but it's not the same as the list size. As size of list needs to be bigger than the size of array, the List implementation will allocate a bigger array (factor of 2 maybe less) and will copy all items from old array to the new one plus newly added items.

So, if you know that you may have from, say, 50 to 60 items in your list, create a list with capacity 60 and no memory deallocation will happen.

Note: And it looks like Garbage Collector will not have to clean up old arrays

evhen14
  • 1,839
  • 12
  • 16
0

This all lies in one line for ensuring the capacity is able to store another element:

int num = this._items.Length == 0 ? 4 : this._items.Length * 2;

Got this from the mscorlib 4.0.0.0 deassebled - of course, as Jon said, this cannot be guaranteed not to change in the future (so far it still stays at 0, 4, 8, 16...).

Of course, you could set it yourself so this can be 3, 9, 27 etc.

tomkuj
  • 81
  • 1
  • 5
  • 1
    You mean 3, 6, 12, etc. (It always doubles, starting with the initial capacity provided.) – yoyo Mar 18 '14 at 05:57
  • 1
    @yoyo, I think that when tomkuj says "Of course, you could set it yourself so this can be 3, 9, 27 etc." this is just demonstrating a few arbitrary random numbers one could pick as the capacity value in the List initialization rather than demonstrating the doubling. – jboeke Jan 13 '20 at 17:22