Generic Lists (List<T>)

A single variable holds one value — but real programs juggle collections : a shopping cart, a list of scores, a feed of messages. is the workhorse collection of C#: an ordered, resizable container that grows as you add and shrinks as you remove. Master it and you can model almost any "many things" you'll meet.

Learn Generic Lists (List<T>) in our free C# course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick recall.

Part of the free C# course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

An array is a row of fixed, numbered parking bays — once the car park is built, you can't add a bay. A is a queue at a coffee shop : people join the back, someone leaves from the middle, the line stretches and contracts naturally, and everyone still has a clear position. That flexibility — adding and removing without rebuilding everything — is exactly why List is the default collection.

1. Creating & Reading a List

Declare a list by stating what it holds: for text, for numbers. Add items with Add , read one by its zero-based index with list[0] (or list[^1] for the last), and ask how many there are with Count . A foreach loop is the tidiest way to visit every element.

2. Modifying a List

Lists shine because they change shape. Insert places an item at a position, Remove deletes the first matching value, RemoveAt deletes by index, and Clear empties the whole thing. Contains and IndexOf answer "is it in here, and where?".

Your turn. Manage a small shopping cart — add one item, remove another, and print the result.

3. Sorting, Searching & Aggregating

Once you have a list of numbers, a whole toolbox opens up. Sort and Reverse reorder it in place; the LINQ helpers Sum , Max , Min and Average compute totals without a loop; and Find / FindAll pull out items matching a condition you express with a lambda ( n => n > 4 ).

A classic bug: removing items while iterating a list with foreach . C# detects the collection changed underneath the loop and throws InvalidOperationException . The clean fix is RemoveAll with a predicate, which does the whole job safely in one call.

If you must remove inside a loop yourself, iterate backwards with a for loop ( for (int i = list.Count - 1; i >= 0; i--) ) so removing an item doesn't shift indexes you haven't visited yet.

These six lines build a number list, drop the odd values, sort it, and print 2, 4, 6 . Put them in a working order.

Why: the list must exist before anything operates on it. Removing the odds first leaves 2, 6, 4 , then Sort orders them to 2, 4, 6 , and the WriteLine prints the final state. Sorting before removing would still work here, but removing first keeps the list smaller to sort.

20 — RemoveAt(0) drops 10 and everything shifts down, so index 0 is now 20 .

3 — after sorting, the list is 1, 2, 3 , and [^1] is the last element, 3 .

13 — Sum() adds 4 + 8 + 1 . (Requires using System.Linq; .)

Combine adding, filtering with RemoveAll , sorting, and aggregating into a small scores report. The outline is in the comments.

Practice quiz

What is the main difference between an array and a List<T> in C#?

  • A List is always faster than an array
  • A List grows and shrinks automatically, while an array has a fixed size
  • An array can hold mixed types but a List cannot
  • A List can only hold reference types

Answer: A List grows and shrinks automatically, while an array has a fixed size. An array's size is fixed at creation; a List<T> resizes automatically as you Add and Remove, which is why it is the default collection.

What does the <T> in List<T> represent?

  • The total number of items
  • A type parameter — the kind of element the list holds
  • A threading mode
  • A temporary variable

Answer: A type parameter — the kind of element the list holds. T is a type parameter you fill in when creating the list, so List<int> holds ints and List<string> holds strings, type-checked at compile time.

What does list[^1] return?

  • The first element
  • The element at index 1
  • The last element (one from the end)
  • The count of the list

Answer: The last element (one from the end). The ^1 index counts from the end, so list[^1] is the last element — cleaner than list[list.Count - 1].

What is the correct, safe way to remove every item matching a condition?

  • Remove items inside a foreach over the same list
  • Use RemoveAll with a predicate
  • Call Clear() then re-add the keepers
  • Set each matching item to null

Answer: Use RemoveAll with a predicate. RemoveAll(predicate) removes every match in one call. Removing inside a foreach over the same list throws InvalidOperationException.

What happens if you modify a List inside a foreach loop over that same list?

  • It silently skips the modified item
  • It throws InvalidOperationException
  • It sorts the list automatically
  • Nothing — it is fully supported

Answer: It throws InvalidOperationException. C# detects the collection changed underneath the loop and throws InvalidOperationException. Use RemoveAll or a backward for loop instead.

What does RemoveAt(0) do to a list of { 10, 20, 30 }?

  • Removes 10, leaving { 20, 30 }
  • Removes 0 items
  • Removes the last item
  • Removes the value 0

Answer: Removes 10, leaving { 20, 30 }. RemoveAt(0) removes the item at index 0 (the value 10); everything shifts down, so index 0 becomes 20.

Which using directive must be imported to call list.Sum(), Max(), and Average()?

  • System.Text
  • System.Collections.Generic
  • System.Linq
  • System.IO

Answer: System.Linq. Sum, Max, Min, and Average are LINQ extension methods that live in System.Linq.

What does the Sort() method do to a List<int>?

  • Returns a new sorted list and leaves the original unchanged
  • Sorts the list in place, mutating it
  • Removes duplicates
  • Reverses the list

Answer: Sorts the list in place, mutating it. Sort() mutates the list in place, reordering its elements; it does not return a new list.

What does Remove("x") do if "x" is not in the list?

  • Throws an exception
  • Removes the first item instead
  • Returns false and changes nothing
  • Adds "x" to the list

Answer: Returns false and changes nothing. Remove deletes the first matching value and returns true; if the value is absent it returns false and the list is unchanged.

Which namespace must you import to declare a List<T>?

  • System.Linq
  • System.Collections.Generic
  • System.Text
  • System

Answer: System.Collections.Generic. List<T> lives in System.Collections.Generic, so that namespace must be imported (most editors add it automatically).