Start learning free

LESSON 98 OF 347 · ARRAYS I

Array Pop in C#: Removing the Last Item from a List

Lesson Read the full explanation

Another way to change the data in an List is with the .Remove() method.

.Remove() takes one parameter which represents an index and removes the element placed at that index:

List<int> threeArr = new List<>(List.of(1, 4, 6));

// Remove second element:
threeArr.Remove(1);

// threeArray has now the value {1, 6}

// Remove first element:
threeArr.Remove(0);

// threeArray has now the value {6}

Assignment
Follow the Coding Tutorial and let's play with some arrays.


Hint
Look at the examples above if you get stuck.


STEP 1 OF 2
    Ctrl + Enter to check

    C# · ARRAYS I

    Array Pop in C#, explained

    No Pop on a list

    In some languages, a method named pop removes the last item of an array and hands it back. C#'s List<T> has no such method. Instead it has methods that remove by position or by value, and removing the last item is just the case where the position is the final one.

    The two methods to know are:

    • RemoveAt(index) deletes the item at a position.
    • Remove(value) deletes the first item that equals a value.

    The lesson needs the first one.

    RemoveAt and the last index

    List indexes start at 0, and a list with Count items has valid indexes 0 to Count - 1. So the last item is always at Count - 1:

    List<int> numbers = new List<int> { 1, 4, 6 };
    
    numbers.RemoveAt(numbers.Count - 1);
    Console.WriteLine(string.Join(", ", numbers)); // 1, 4
    
    numbers.RemoveAt(0);
    Console.WriteLine(string.Join(", ", numbers)); // 4
    

    Everything after the removed item shifts one place to the left, and Count drops by one. That is why the same expression numbers.Count - 1 points at a different item on the next call: it always means "the current last item".

    Count is a property, so it takes no parentheses. Arrays use Length, but a list uses Count.

    Remove is not RemoveAt

    This is the trap of the topic. Remove takes a value, not an index, and it returns a bool that says whether it found something to remove:

    List<int> list = new List<int> { 1, 4, 6, 1 };
    
    Console.WriteLine(list.Remove(1));             // True
    Console.WriteLine(string.Join(", ", list));    // 4, 6, 1
    Console.WriteLine(list.Remove(99));            // False
    

    Here Remove(1) deleted the first item equal to 1, not the item at index 1, and it left the second 1 alone. On a List<int> the two methods are easy to mix up because both take an int. If you have a position, call RemoveAt.

    Getting the value before you remove it

    RemoveAt returns nothing. If you want the removed item, as pop would give you, read it first:

    List<string> names = new List<string> { "Ann", "Bo", "Cy" };
    
    string last = names[names.Count - 1];
    names.RemoveAt(names.Count - 1);
    
    Console.WriteLine(last);                    // Cy
    Console.WriteLine(string.Join(", ", names)); // Ann, Bo
    

    Removing the first item, and many items

    The same method handles the front of the list. RemoveAt(0) drops the first item. Removing from the end is cheap, because nothing after it has to move. Removing from the front or the middle is slower on a long list, since every later item shifts left by one place.

    Because the removed item is gone for good, decide whether you need its value before the call, not after it.

    To clear a whole list, call Clear(). To remove a run of items, RemoveRange(start, count) takes the first index and how many items to delete.

    The exercise, step by step

    The lesson starts with these lists:

    List<string> fruits = new List<string>(new[] {"mango", "kiwi", "grapefruit"});
    List<int> ages = new List<int>(new[] {14, 32, 50, 21});
    
    1. Remove the last fruit. Call fruits.RemoveAt(fruits.Count - 1);. The last index is Count - 1, which is 2 here, so "grapefruit" goes and mango, kiwi remain.
    2. Remove two ages. Call ages.RemoveAt(ages.Count - 1); twice. The first call removes 21, which shrinks the list to three items. The same expression now points at 50, so the second call removes that. The list ends as 14, 32.

    The complete solution is:

    List<string> fruits = new List<string>(new[] {"mango", "kiwi", "grapefruit"});
    List<int> ages = new List<int>(new[] {14, 32, 50, 21});
    
    fruits.RemoveAt(fruits.Count - 1);
    ages.RemoveAt(ages.Count - 1);
    ages.RemoveAt(ages.Count - 1);
    

    Common mistakes

    • Removing from an empty list. With Count equal to 0, the index Count - 1 is -1, and RemoveAt throws an ArgumentOutOfRangeException. Check Count > 0 first when the list might be empty.
    • Using Count instead of Count - 1. The index Count is one past the end, so it is out of range and throws.
    • Calling Remove when you mean RemoveAt. Remove(2) looks for the value 2, not position 2.
    • Using a fixed index. RemoveAt(3) works for a four-item list only. The expression Count - 1 keeps working as the list changes.
    • Expecting the removed value back. RemoveAt is a statement, not an expression with a result.

    Key takeaways

    • List<T> has no Pop; use RemoveAt(list.Count - 1) to drop the last item.
    • RemoveAt takes an index. Remove takes a value and removes its first match.
    • Items after a removed one shift left, and Count goes down by one.
    • Read the item before removing it when you need its value.
    Keep going with C#About 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free