In cases when the capacity is part of IEnumerable<T> that is also an ICollection<T>, the library will allocate at the correct capacity.
Here is a reference implementation of List<T>(IEnumerable<T> source), which is invoked when you call ToList():
public List(IEnumerable<T> collection) {
if (collection==null)
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection);
Contract.EndContractBlock();
ICollection<T> c = collection as ICollection<T>;
if( c != null) {
int count = c.Count;
if (count == 0) {
_items = _emptyArray;
} else {
_items = new T[count];
c.CopyTo(_items, 0);
_size = count;
}
} else {
_size = 0;
_items = _emptyArray;
// This enumerable could be empty. Let Add allocate a new array, if needed.
// Note it will also go to _defaultCapacity first, not 1, then 2, etc.
using(IEnumerator<T> en = collection.GetEnumerator()) {
while(en.MoveNext()) {
Add(en.Current);
}
}
}
}
Note how the constructor behaves when collection implements ICollection<T>: rather than iterating the content and calling Add for each item, it allocates the internal _items array, and copies the content into it without reallocations.
In situations when the capacity is not embedded in class implementing IEnumerable<T>, you can easily define one yourself, using a combination of standard methods:
public static class ToListExtension {
public static List<T> ToList<T>(this IEnumerable<T> source, int capacity)
{
var res = new List<T>(capacity);
res.AddRange(source);
return res;
}
}