List<T>: the everyday collection
Store, grow, search and reorder sequences of items with List<T>.
11 min read
You will learn
- Create lists and add, insert and remove items
- Search and sort lists
- Know when to use a list instead of an array
- Avoid modifying a list while looping over it
Arrays that grow
Arrays have a fixed size. Most real data doesn't: a shopping cart, the lines of a file, search results. List<T> is the collection you'll use more than any other — an ordered sequence that grows and shrinks as needed.
var cart = new List<string>(); // empty
cart.Add("Coffee");
cart.Add("Bread");
cart.Add("Milk");
Console.WriteLine(cart.Count); // 3
Console.WriteLine(cart[0]); // Coffee — indexes work like arraysCreate one with initial items:
var primes = new List<int> { 2, 3, 5, 7 };
List<string> colors = ["red", "green"]; // C# 12 collection expression
var copy = new List<int>(primes); // an independent copyAdding and removing
| Method | Effect |
|---|---|
Add(item) | Append at the end |
AddRange(items) | Append several |
Insert(index, item) | Insert at a position, shifting the rest |
Remove(item) | Remove the first matching item (returns bool) |
RemoveAt(index) | Remove at a position |
RemoveAll(condition) | Remove every item matching a condition (returns the count) |
Clear() | Remove everything |
cart.Insert(0, "Eggs"); // Eggs, Coffee, Bread, Milk
cart.Remove("Bread"); // Eggs, Coffee, Milk
cart.RemoveAll(item => item.StartsWith("M")); // Eggs, Coffeeitem => item.StartsWith("M") is a lambda — a small inline function. You'll learn them properly in Track 4.
Searching
cart.Contains("Coffee"); // true
cart.IndexOf("Coffee"); // 1, or -1 if missing
cart.Find(item => item.Length > 4); // first match, or null
cart.Exists(item => item == "Tea"); // falseSorting and reordering
var scores = new List<int> { 70, 95, 82 };
scores.Sort(); // 70, 82, 95 — in place
scores.Reverse(); // 95, 82, 70
var people = new List<Person> { ... };
people.Sort((a, b) => a.Age.CompareTo(b.Age)); // sort by a custom ruleLists vs arrays
Array T[] | List<T> | |
|---|---|---|
| Size | Fixed | Grows and shrinks |
| Count property | Length | Count |
| Add / Remove | ✗ | ✓ |
Indexing x[i] | ✓ | ✓ |
| Best for | Fixed-size data, performance-critical code | Almost everything else |
Under the hood, a list stores items in an array. When it's full, it allocates a bigger one (double the size) and copies the items over — so Add is fast on average.
Don't modify a list while looping over it
foreach (var item in cart)
{
if (item == "Milk") cart.Remove(item); // 💥 InvalidOperationException
}Instead, use RemoveAll, loop backwards with for (removing doesn't shift the items you haven't visited yet), or build a new list.
Expose read-only views
If a class owns a list, don't let outsiders modify it directly. Expose IReadOnlyList<T> and provide methods like AddItem that keep the class in control.
Try it
C# runtime not loaded
Key takeaways
List<T>is an ordered, resizable collection with index access.Add,Insert,Remove,RemoveAt,RemoveAllchange it;Contains,IndexOf,Findsearch it.- Use
Count, notLength. - Never add or remove items inside a
foreachover the same list.
Exercise
Evens returns a NEW list with only the even numbers. InsertSorted inserts a value into an already-sorted list at the right position, keeping it sorted. RemoveAllOf removes every occurrence of a value and returns how many were removed.
C# runtime not loaded
Hint 1
InsertSorted: find the index of the first element bigger than value (or use sorted.Count if there's none), then sorted.Insert(index, value).
Hint 2
RemoveAllOf: List has a RemoveAll method that takes a condition: items.RemoveAll(item => item == value) — it returns the number removed. Or loop backwards with RemoveAt.
Show solution
var numbers = new List<int> { 1, 3, 5 };
InsertSorted(numbers, 4);
Console.WriteLine(string.Join(", ", numbers));
List<int> Evens(List<int> numbers)
{
var result = new List<int>();
foreach (var n in numbers)
{
if (n % 2 == 0) result.Add(n);
}
return result;
}
void InsertSorted(List<int> sorted, int value)
{
int index = 0;
while (index < sorted.Count && sorted[index] < value)
{
index++;
}
sorted.Insert(index, value);
}
int RemoveAllOf(List<string> items, string value)
{
int removed = 0;
for (int i = items.Count - 1; i >= 0; i--)
{
if (items[i] == value)
{
items.RemoveAt(i);
removed++;
}
}
return removed;
}Quiz
4 questions · 3 correct to pass1.What's the main advantage of List<T> over an array?
2.Which property gives the number of items in a List<T>?
3.What happens if you call list.Remove(item) inside a foreach over the same list?
4.What does `list.IndexOf("x")` return if "x" isn't in the list?
To complete this lesson
- ○ Solve the exercise
- ○ Pass the quiz (3/4 correct)