[c#] How to initialize a List<T> to a given size (as opposed to capacity)?

.NET offers a generic list container whose performance is almost identical (see Performance of Arrays vs. Lists question). However they are quite different in initialization.

Arrays are very easy to initialize with a default value, and by definition they already have certain size:

string[] Ar = new string[10];

Which allows one to safely assign random items, say:

Ar[5]="hello";

with list things are more tricky. I can see two ways of doing the same initialization, neither of which is what you would call elegant:

List<string> L = new List<string>(10);
for (int i=0;i<10;i++) L.Add(null);

or

string[] Ar = new string[10];
List<string> L = new List<string>(Ar);

What would be a cleaner way?

EDIT: The answers so far refer to capacity, which is something else than pre-populating a list. For example, on a list just created with a capacity of 10, one cannot do L[2]="somevalue"

EDIT 2: People wonder why I want to use lists this way, as it is not the way they are intended to be used. I can see two reasons:

  1. One could quite convincingly argue that lists are the "next generation" arrays, adding flexibility with almost no penalty. Therefore one should use them by default. I'm pointing out they might not be as easy to initialize.

  2. What I'm currently writing is a base class offering default functionality as part of a bigger framework. In the default functionality I offer, the size of the List is known in advanced and therefore I could have used an array. However, I want to offer any base class the chance to dynamically extend it and therefore I opt for a list.

This question is related to c# .net generics list initialization

The answer is


You seem to be emphasizing the need for a positional association with your data, so wouldn't an associative array be more fitting?

Dictionary<int, string> foo = new Dictionary<int, string>();
foo[2] = "string";

Use the constructor which takes an int ("capacity") as an argument:

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

EDIT: I should add that I agree with Frederik. You are using the List in a way that goes against the entire reasoning behind using it in the first place.

EDIT2:

EDIT 2: What I'm currently writing is a base class offering default functionality as part of a bigger framework. In the default functionality I offer, the size of the List is known in advanced and therefore I could have used an array. However, I want to offer any base class the chance to dynamically extend it and therefore I opt for a list.

Why would anyone need to know the size of a List with all null values? If there are no real values in the list, I would expect the length to be 0. Anyhow, the fact that this is cludgy demonstrates that it is going against the intended use of the class.


string [] temp = new string[] {"1","2","3"};
List<string> temp2 = temp.ToList();

The accepted answer (the one with the green check mark) has an issue.

The problem:

var result = Lists.Repeated(new MyType(), sizeOfList);
// each item in the list references the same MyType() object
// if you edit item 1 in the list, you are also editing item 2 in the list

I recommend changing the line above to perform a copy of the object. There are many different articles about that:

If you want to initialize every item in your list with the default constructor, rather than NULL, then add the following method:

public static List<T> RepeatedDefaultInstance<T>(int count)
    {
        List<T> ret = new List<T>(count);
        for (var i = 0; i < count; i++)
        {
            ret.Add((T)Activator.CreateInstance(typeof(T)));
        }
        return ret;
    }

List<string> L = new List<string> ( new string[10] );

If you want to initialize the list with N elements of some fixed value:

public List<T> InitList<T>(int count, T initValue)
{
  return Enumerable.Repeat(initValue, count).ToList();
}

string [] temp = new string[] {"1","2","3"};
List<string> temp2 = temp.ToList();

A notice about IList: MSDN IList Remarks: "IList implementations fall into three categories: read-only, fixed-size, and variable-size. (...). For the generic version of this interface, see System.Collections.Generic.IList<T>."

IList<T> does NOT inherits from IList (but List<T> does implement both IList<T> and IList), but is always variable-size. Since .NET 4.5, we have also IReadOnlyList<T> but AFAIK, there is no fixed-size generic List which would be what you are looking for.


You seem to be emphasizing the need for a positional association with your data, so wouldn't an associative array be more fitting?

Dictionary<int, string> foo = new Dictionary<int, string>();
foo[2] = "string";

This is a sample I used for my unit test. I created a list of class object. Then I used forloop to add 'X' number of objects that I am expecting from the service. This way you can add/initialize a List for any given size.

public void TestMethod1()
    {
        var expected = new List<DotaViewer.Interface.DotaHero>();
        for (int i = 0; i < 22; i++)//You add empty initialization here
        {
            var temp = new DotaViewer.Interface.DotaHero();
            expected.Add(temp);
        }
        var nw = new DotaHeroCsvService();
        var items = nw.GetHero();

        CollectionAssert.AreEqual(expected,items);


    }

Hope I was of help to you guys.


Why are you using a List if you want to initialize it with a fixed value ? I can understand that -for the sake of performance- you want to give it an initial capacity, but isn't one of the advantages of a list over a regular array that it can grow when needed ?

When you do this:

List<int> = new List<int>(100);

You create a list whose capacity is 100 integers. This means that your List won't need to 'grow' until you add the 101th item. The underlying array of the list will be initialized with a length of 100.


This is an old question, but I have two solutions. One is fast and dirty reflection; the other is a solution that actually answers the question (set the size not the capacity) while still being performant, which none of the answers here do.


Reflection

This is quick and dirty, and should be pretty obvious what the code does. If you want to speed it up, cache the result of GetField, or create a DynamicMethod to do it:

public static void SetSize<T>(this List<T> l, int newSize) =>
    l.GetType().GetField("_size", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(l, 10);

Obviously a lot of people will be hesitant to put such code into production.


ICollection<T>

This solution is based around the fact that the constructor List(IEnumerable<T> collection) optimizes for ICollection<T> and immediately adjusts the size to the correct amount, without iterating it. It then calls the collections CopyTo to do the copy.

The code is as follows:

public List(IEnumerable<T> collection) {
....
    ICollection<T> c = collection as ICollection<T>;
    if (collection is ICollection<T> c)
    {
        int count = c.Count;
        if (count == 0)
        {
            _items = s_emptyArray;
        }
        else {
            _items = new T[count];
            c.CopyTo(_items, 0);
            _size = count;
        }
    }    

So we can completely optimally pre-initialize the List to the correct size, without any extra copying.

How so? By creating an ICollection<T> object that does nothing other than return a Count. Specifically, we will not implement anything in CopyTo which is the only other function called.

private class SizeCollection<T> : ICollection<T>
{
    public SizeCollection(int size) =>
        Count = size;

    public void Add(T i){}
    public void Clear(){}
    public bool Contains(T i)=>true;
    public void CopyTo(T[]a, int i){}
    public bool Remove(T i)=>true;
    public int Count {get;}
    public bool IsReadOnly=>true;
    public IEnumerator<T> GetEnumerator()=>null;
    IEnumerator IEnumerable.GetEnumerator()=>null;
}

public List<T> InitializedList<T>(int size) =>
    new List<T>(new SizeCollection<T>(size));

We could in theory do the same thing for AddRange/InsertRange for an existing array, which also accounts for ICollection<T>, but the code there creates a new array for the supposed items, then copies them in. In such case, it would be faster to just empty-loop Add:

public void SetSize<T>(this List<T> l, int size)
{
    if(size < l.Count)
        l.RemoveRange(size, l.Count - size);
    else
        for(size -= l.Count; size > 0; size--)
            l.Add(default(T));
}

If you want to initialize the list with N elements of some fixed value:

public List<T> InitList<T>(int count, T initValue)
{
  return Enumerable.Repeat(initValue, count).ToList();
}

Use the constructor which takes an int ("capacity") as an argument:

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

EDIT: I should add that I agree with Frederik. You are using the List in a way that goes against the entire reasoning behind using it in the first place.

EDIT2:

EDIT 2: What I'm currently writing is a base class offering default functionality as part of a bigger framework. In the default functionality I offer, the size of the List is known in advanced and therefore I could have used an array. However, I want to offer any base class the chance to dynamically extend it and therefore I opt for a list.

Why would anyone need to know the size of a List with all null values? If there are no real values in the list, I would expect the length to be 0. Anyhow, the fact that this is cludgy demonstrates that it is going against the intended use of the class.


A bit late but first solution you proposed seems far cleaner to me : you dont allocate memory twice. Even List constrcutor needs to loop through array in order to copy it; it doesn't even know by advance there is only null elements inside.

1. - allocate N - loop N Cost: 1 * allocate(N) + N * loop_iteration

2. - allocate N - allocate N + loop () Cost : 2 * allocate(N) + N * loop_iteration

However List's allocation an loops might be faster since List is a built-in class, but C# is jit-compiled sooo...


Why are you using a List if you want to initialize it with a fixed value ? I can understand that -for the sake of performance- you want to give it an initial capacity, but isn't one of the advantages of a list over a regular array that it can grow when needed ?

When you do this:

List<int> = new List<int>(100);

You create a list whose capacity is 100 integers. This means that your List won't need to 'grow' until you add the 101th item. The underlying array of the list will be initialized with a length of 100.


string [] temp = new string[] {"1","2","3"};
List<string> temp2 = temp.ToList();

A notice about IList: MSDN IList Remarks: "IList implementations fall into three categories: read-only, fixed-size, and variable-size. (...). For the generic version of this interface, see System.Collections.Generic.IList<T>."

IList<T> does NOT inherits from IList (but List<T> does implement both IList<T> and IList), but is always variable-size. Since .NET 4.5, we have also IReadOnlyList<T> but AFAIK, there is no fixed-size generic List which would be what you are looking for.


You seem to be emphasizing the need for a positional association with your data, so wouldn't an associative array be more fitting?

Dictionary<int, string> foo = new Dictionary<int, string>();
foo[2] = "string";

The accepted answer (the one with the green check mark) has an issue.

The problem:

var result = Lists.Repeated(new MyType(), sizeOfList);
// each item in the list references the same MyType() object
// if you edit item 1 in the list, you are also editing item 2 in the list

I recommend changing the line above to perform a copy of the object. There are many different articles about that:

If you want to initialize every item in your list with the default constructor, rather than NULL, then add the following method:

public static List<T> RepeatedDefaultInstance<T>(int count)
    {
        List<T> ret = new List<T>(count);
        for (var i = 0; i < count; i++)
        {
            ret.Add((T)Activator.CreateInstance(typeof(T)));
        }
        return ret;
    }

Why are you using a List if you want to initialize it with a fixed value ? I can understand that -for the sake of performance- you want to give it an initial capacity, but isn't one of the advantages of a list over a regular array that it can grow when needed ?

When you do this:

List<int> = new List<int>(100);

You create a list whose capacity is 100 integers. This means that your List won't need to 'grow' until you add the 101th item. The underlying array of the list will be initialized with a length of 100.


Initializing the contents of a list like that isn't really what lists are for. Lists are designed to hold objects. If you want to map particular numbers to particular objects, consider using a key-value pair structure like a hash table or dictionary instead of a list.


You can use Linq to cleverly initialize your list with a default value. (Similar to David B's answer.)

var defaultStrings = (new int[10]).Select(x => "my value").ToList();

Go one step farther and initialize each string with distinct values "string 1", "string 2", "string 3", etc:

int x = 1;
var numberedStrings = (new int[10]).Select(x => "string " + x++).ToList();

Create an array with the number of items you want first and then convert the array in to a List.

int[] fakeArray = new int[10];

List<int> list = fakeArray.ToList();

You seem to be emphasizing the need for a positional association with your data, so wouldn't an associative array be more fitting?

Dictionary<int, string> foo = new Dictionary<int, string>();
foo[2] = "string";

Initializing the contents of a list like that isn't really what lists are for. Lists are designed to hold objects. If you want to map particular numbers to particular objects, consider using a key-value pair structure like a hash table or dictionary instead of a list.


If I understand correctly, you want the List<T> version of new T[size], without the overhead of adding values to it.

If you are not afraid the implementation of List<T> will change dramatically in the future (and in this case I believe the probability is close to 0), you can use reflection:

    public static List<T> NewOfSize<T>(int size) {
        var list = new List<T>(size);
        var sizeField = list.GetType().GetField("_size",BindingFlags.Instance|BindingFlags.NonPublic);
        sizeField.SetValue(list, size);
        return list;
    }

Note that this takes into account the default functionality of the underlying array to prefill with the default value of the item type. All int arrays will have values of 0 and all reference type arrays will have values of null. Also note that for a list of reference types, only the space for the pointer to each item is created.

If you, for some reason, decide on not using reflection, I would have liked to offer an option of AddRange with a generator method, but underneath List<T> just calls Insert a zillion times, which doesn't serve.

I would also like to point out that the Array class has a static method called ResizeArray, if you want to go the other way around and start from Array.

To end, I really hate when I ask a question and everybody points out that it's the wrong question. Maybe it is, and thanks for the info, but I would still like an answer, because you have no idea why I am asking it. That being said, if you want to create a framework that has an optimal use of resources, List<T> is a pretty inefficient class for anything than holding and adding stuff to the end of a collection.


Why are you using a List if you want to initialize it with a fixed value ? I can understand that -for the sake of performance- you want to give it an initial capacity, but isn't one of the advantages of a list over a regular array that it can grow when needed ?

When you do this:

List<int> = new List<int>(100);

You create a list whose capacity is 100 integers. This means that your List won't need to 'grow' until you add the 101th item. The underlying array of the list will be initialized with a length of 100.


This is an old question, but I have two solutions. One is fast and dirty reflection; the other is a solution that actually answers the question (set the size not the capacity) while still being performant, which none of the answers here do.


Reflection

This is quick and dirty, and should be pretty obvious what the code does. If you want to speed it up, cache the result of GetField, or create a DynamicMethod to do it:

public static void SetSize<T>(this List<T> l, int newSize) =>
    l.GetType().GetField("_size", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(l, 10);

Obviously a lot of people will be hesitant to put such code into production.


ICollection<T>

This solution is based around the fact that the constructor List(IEnumerable<T> collection) optimizes for ICollection<T> and immediately adjusts the size to the correct amount, without iterating it. It then calls the collections CopyTo to do the copy.

The code is as follows:

public List(IEnumerable<T> collection) {
....
    ICollection<T> c = collection as ICollection<T>;
    if (collection is ICollection<T> c)
    {
        int count = c.Count;
        if (count == 0)
        {
            _items = s_emptyArray;
        }
        else {
            _items = new T[count];
            c.CopyTo(_items, 0);
            _size = count;
        }
    }    

So we can completely optimally pre-initialize the List to the correct size, without any extra copying.

How so? By creating an ICollection<T> object that does nothing other than return a Count. Specifically, we will not implement anything in CopyTo which is the only other function called.

private class SizeCollection<T> : ICollection<T>
{
    public SizeCollection(int size) =>
        Count = size;

    public void Add(T i){}
    public void Clear(){}
    public bool Contains(T i)=>true;
    public void CopyTo(T[]a, int i){}
    public bool Remove(T i)=>true;
    public int Count {get;}
    public bool IsReadOnly=>true;
    public IEnumerator<T> GetEnumerator()=>null;
    IEnumerator IEnumerable.GetEnumerator()=>null;
}

public List<T> InitializedList<T>(int size) =>
    new List<T>(new SizeCollection<T>(size));

We could in theory do the same thing for AddRange/InsertRange for an existing array, which also accounts for ICollection<T>, but the code there creates a new array for the supposed items, then copies them in. In such case, it would be faster to just empty-loop Add:

public void SetSize<T>(this List<T> l, int size)
{
    if(size < l.Count)
        l.RemoveRange(size, l.Count - size);
    else
        for(size -= l.Count; size > 0; size--)
            l.Add(default(T));
}

Create an array with the number of items you want first and then convert the array in to a List.

int[] fakeArray = new int[10];

List<int> list = fakeArray.ToList();

List<string> L = new List<string> ( new string[10] );

Initializing the contents of a list like that isn't really what lists are for. Lists are designed to hold objects. If you want to map particular numbers to particular objects, consider using a key-value pair structure like a hash table or dictionary instead of a list.


string [] temp = new string[] {"1","2","3"};
List<string> temp2 = temp.ToList();

If you want to initialize the list with N elements of some fixed value:

public List<T> InitList<T>(int count, T initValue)
{
  return Enumerable.Repeat(initValue, count).ToList();
}

Initializing the contents of a list like that isn't really what lists are for. Lists are designed to hold objects. If you want to map particular numbers to particular objects, consider using a key-value pair structure like a hash table or dictionary instead of a list.


A bit late but first solution you proposed seems far cleaner to me : you dont allocate memory twice. Even List constrcutor needs to loop through array in order to copy it; it doesn't even know by advance there is only null elements inside.

1. - allocate N - loop N Cost: 1 * allocate(N) + N * loop_iteration

2. - allocate N - allocate N + loop () Cost : 2 * allocate(N) + N * loop_iteration

However List's allocation an loops might be faster since List is a built-in class, but C# is jit-compiled sooo...


If you want to initialize the list with N elements of some fixed value:

public List<T> InitList<T>(int count, T initValue)
{
  return Enumerable.Repeat(initValue, count).ToList();
}

This is a sample I used for my unit test. I created a list of class object. Then I used forloop to add 'X' number of objects that I am expecting from the service. This way you can add/initialize a List for any given size.

public void TestMethod1()
    {
        var expected = new List<DotaViewer.Interface.DotaHero>();
        for (int i = 0; i < 22; i++)//You add empty initialization here
        {
            var temp = new DotaViewer.Interface.DotaHero();
            expected.Add(temp);
        }
        var nw = new DotaHeroCsvService();
        var items = nw.GetHero();

        CollectionAssert.AreEqual(expected,items);


    }

Hope I was of help to you guys.


You can use Linq to cleverly initialize your list with a default value. (Similar to David B's answer.)

var defaultStrings = (new int[10]).Select(x => "my value").ToList();

Go one step farther and initialize each string with distinct values "string 1", "string 2", "string 3", etc:

int x = 1;
var numberedStrings = (new int[10]).Select(x => "string " + x++).ToList();

Use the constructor which takes an int ("capacity") as an argument:

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

EDIT: I should add that I agree with Frederik. You are using the List in a way that goes against the entire reasoning behind using it in the first place.

EDIT2:

EDIT 2: What I'm currently writing is a base class offering default functionality as part of a bigger framework. In the default functionality I offer, the size of the List is known in advanced and therefore I could have used an array. However, I want to offer any base class the chance to dynamically extend it and therefore I opt for a list.

Why would anyone need to know the size of a List with all null values? If there are no real values in the list, I would expect the length to be 0. Anyhow, the fact that this is cludgy demonstrates that it is going against the intended use of the class.


If I understand correctly, you want the List<T> version of new T[size], without the overhead of adding values to it.

If you are not afraid the implementation of List<T> will change dramatically in the future (and in this case I believe the probability is close to 0), you can use reflection:

    public static List<T> NewOfSize<T>(int size) {
        var list = new List<T>(size);
        var sizeField = list.GetType().GetField("_size",BindingFlags.Instance|BindingFlags.NonPublic);
        sizeField.SetValue(list, size);
        return list;
    }

Note that this takes into account the default functionality of the underlying array to prefill with the default value of the item type. All int arrays will have values of 0 and all reference type arrays will have values of null. Also note that for a list of reference types, only the space for the pointer to each item is created.

If you, for some reason, decide on not using reflection, I would have liked to offer an option of AddRange with a generator method, but underneath List<T> just calls Insert a zillion times, which doesn't serve.

I would also like to point out that the Array class has a static method called ResizeArray, if you want to go the other way around and start from Array.

To end, I really hate when I ask a question and everybody points out that it's the wrong question. Maybe it is, and thanks for the info, but I would still like an answer, because you have no idea why I am asking it. That being said, if you want to create a framework that has an optimal use of resources, List<T> is a pretty inefficient class for anything than holding and adding stuff to the end of a collection.


Examples related to c#

How can I convert this one line of ActionScript to C#? Microsoft Advertising SDK doesn't deliverer ads How to use a global array in C#? How to correctly write async method? C# - insert values from file into two arrays Uploading into folder in FTP? Are these methods thread safe? dotnet ef not found in .NET Core 3 HTTP Error 500.30 - ANCM In-Process Start Failure Best way to "push" into C# array

Examples related to .net

You must add a reference to assembly 'netstandard, Version=2.0.0.0 How to use Bootstrap 4 in ASP.NET Core No authenticationScheme was specified, and there was no DefaultChallengeScheme found with default authentification and custom authorization .net Core 2.0 - Package was restored using .NetFramework 4.6.1 instead of target framework .netCore 2.0. The package may not be fully compatible Update .NET web service to use TLS 1.2 EF Core add-migration Build Failed What is the difference between .NET Core and .NET Standard Class Library project types? Visual Studio 2017 - Could not load file or assembly 'System.Runtime, Version=4.1.0.0' or one of its dependencies Nuget connection attempt failed "Unable to load the service index for source" Token based authentication in Web API without any user interface

Examples related to generics

Instantiating a generic type Are these methods thread safe? The given key was not present in the dictionary. Which key? Using Java generics for JPA findAll() query with WHERE clause Using Spring RestTemplate in generic method with generic parameter How to create a generic array? Create a List of primitive int? How to have Java method return generic list of any type? Create a new object from type parameter in generic class What is the "proper" way to cast Hibernate Query.list() to List<Type>?

Examples related to list

Convert List to Pandas Dataframe Column Python find elements in one list that are not in the other Sorting a list with stream.sorted() in Java Python Loop: List Index Out of Range How to combine two lists in R How do I multiply each element in a list by a number? Save a list to a .txt file The most efficient way to remove first N elements in a list? TypeError: list indices must be integers or slices, not str Parse JSON String into List<string>

Examples related to initialization

"error: assignment to expression with array type error" when I assign a struct field (C) How to set default values in Go structs How to declare an ArrayList with values? Initialize array of strings Initializing a dictionary in python with a key value and no corresponding values Declare and Initialize String Array in VBA VBA (Excel) Initialize Entire Array without Looping Default values and initialization in Java Initializing array of structures C char array initialization