Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>The reason is that you don't <em>add</em> to the list with the indexer, you <em>replace existing items</em>.</p> <p>Since you have not yet added any items to the list, it is empty, and any attempt at using the indexer to "add" items to it will throw that exception.</p> <p>This:</p> <pre><code>new List&lt;string&gt;(11); </code></pre> <p>does not create a list with 11 elements, it creates a list with capacity for 11 elements initially. This is an optimization. If you add more elements, the list will have to be resized internally, and you can pass in the expected or known capacity to avoid too many of those resizes.</p> <p>Here's a <a href="http://linqpad.net" rel="nofollow noreferrer">LINQPad</a> program that demonstrates:</p> <pre><code>void Main() { var l = new List&lt;string&gt;(10); l.Dump(); // empty list l.Add("Item"); l.Dump(); // one item l[0] = "Other item"; l.Dump(); // still one item l.Capacity.Dump(); // should be 10 l.AddRange(Enumerable.Range(1, 20).Select(idx =&gt; idx.ToString())); l.Capacity.Dump(); // should be 21 or more } </code></pre> <p>Output:</p> <p><img src="https://i.stack.imgur.com/Jj6Uk.png" alt="output of linqpad program"></p> <hr> <p><strong>Internals</strong></p> <p>Internally, inside a <code>List&lt;T&gt;</code>, an array is actually used to hold the elements. Additionally, a <code>Count</code> property/value is kept to keep track of how many of those array elements have actually been used.</p> <p>When you construct an empty list, not passing in a capacity, a default one is used, and this is the initial size of that array.</p> <p>As you keep adding new elements to the list, slowly you will fill up that array, towards the end. Once you have filled the entire array, and add another element to it, a new, bigger, array will have to be constructed. All the elements in the old array are then copied over to this new, bigger, array, and from now on, that array is used instead.</p> <p>That is why the internal code calls that <code>EnsureCapacity</code> method. This method is the one doing the resize operation, if necessary.</p> <p>Every time the array has to be resized, a new array is constructed and all the elements copied over. As the array grows, this operation grows in cost. It's not <em>all</em> that much, but it still isn't free.</p> <p>That is why, if you know that you will need to store, say, 1000 elements in the list, it is a good idea to pass in a capacity value to begin with. That way, the initial size of that array might be large enough to never need to be resized/replaced. At the same time, it's not a good idea to just pass in a very large value for capacity, as this might end up using a lot of memory unnecessary.</p> <p>Also know that everything in this section of the answer is undocumented (as far as I know) behavior, and should any details or specific behavior you might learn from it should never influence the code you write, other than the knowledge about passing in a good capacity value.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload