Arrays versus lists
Many languages let you "push" a new item onto the end of an array. In C#, a real array such as int[] has a fixed length that you choose when you create it, so it can't grow. When you need a collection that grows, you use List<T> from System.Collections.Generic. A list keeps its items in order, lets you read them by index like an array, and resizes itself as you add to it.
The C# version of "push" is the Add method. It takes one item and places it at the end of the list.
Using Add
Create a list with a collection initializer, then call Add:
List<int> numbers = new List<int> { 1, 2, 3 };
numbers.Add(4);
Console.WriteLine(string.Join(", ", numbers)); // 1, 2, 3, 4
Console.WriteLine(numbers.Count); // 4
A few details are worth knowing:
- The item must match the list's type. A
List<int>accepts integers and aList<string>accepts strings.numbers.Add("five")is a compile error. Addchanges the list in place. It returns nothing, so there is no new list to capture. Writenumbers.Add(4);on its own line.- One item per call. To add several items, call
Addseveral times, or useAddRangewith another collection. Countgrows by one each time. It is a property, so it has no parentheses. The size of an array isLength, and the size of a list isCount.
Building a list from an array
A list can be created from an existing array. The new list is a copy, and adding to it doesn't affect the array:
string[] source = { "mango", "kiwi" };
List<string> fruits = new List<string>(source);
fruits.Add("pear");
Console.WriteLine(fruits.Count); // 3
Console.WriteLine(source.Length); // 2
Code written for other languages sometimes tries new List<int>(List.of(1, 2, 3)) or new List<>(...). Neither is valid C#. Use a collection initializer, or pass an array or another collection to the constructor, and write the type argument yourself.
Adding in the middle and adding many
Two related methods cover cases that Add doesn't:
List<int> list = new List<int> { 1, 2, 3 };
list.AddRange(new[] { 4, 5 }); // 1, 2, 3, 4, 5
list.Insert(0, 0); // 0, 1, 2, 3, 4, 5
AddRange appends every item of another collection in one call. Insert(index, item) puts an item at a position and shifts the later items to the right. Plain Add is the cheapest of the three because nothing has to move.
How a list grows
Inside, a List<T> keeps an array. When that array is full, the list allocates a bigger one and copies the items across, so you never have to manage sizes yourself. For the code you write, the effect is simple: Add always succeeds, and the new item is always at index Count - 1.
The exercise, step by step
The lesson starts with two lists:
List<string> fruits = new List<string>(new[] {"mango", "kiwi", "grapefruit"});
List<int> ages = new List<int>(new[] {14, 32, 50, 21});
- Add a fruit. Call
Addonfruitswith the new fruit's name as a string, as in the solution below. It goes after the three existing fruits, so the list now has four items and the new one is last. - Add two ages.
Addinserts one element per call, so write two calls:ages.Add(10);first andages.Add(23);second. The order matters, because each call appends after the previous one. The list ends as14, 32, 50, 21, 10, 23.
The solution is:
fruits.Add("apple");
ages.Add(10);
ages.Add(23);
Run it and ages holds 14, 32, 50, 21, 10, 23, while fruits has four items with the new one last.
Common mistakes
- Calling
Addon an array. Arrays have noAddmethod. If the collection has to grow, declare aList<T>. - Using the wrong casing. C# is case-sensitive, and the method is
Add. Writingadd, or thepushandappendnames from other languages, doesn't compile. - Expecting a return value.
Addreturns nothing, sovar more = fruits.Add("x");is an error. - Adding the values in the wrong order. Each call goes to the end, so
Add(23)beforeAdd(10)would leave 10 last.
Key takeaways
- Arrays have a fixed length;
List<T>grows. list.Add(item)appends one item to the end of the list and changes the list in place.- Use
Countfor a list's size andLengthfor an array's.