How to Remove Elements from a List in C#

List<T> in C# has five removal methods, and the right one depends on what you know about the element. Remove(item) deletes the first element equal to a value. RemoveAt(index) deletes the element at a position. RemoveAll(predicate) deletes every element that matches a condition. RemoveRange(index, count) deletes a block, and Clear() empties the list.

All five belong to List<T> in System.Collections.Generic. LINQ has no Remove or RemoveAll method, because LINQ never changes its source. The LINQ way is to build a new list with Where, which is covered below.

Remove by value with Remove

Remove scans from the start and deletes the first element equal to its argument. It returns true when it removed something and false when nothing matched.

var fruits = new List<string> { "apple", "banana", "cherry", "banana" }; bool removed = fruits.Remove("banana"); // true; list is apple, cherry, banana bool missing = fruits.Remove("grape"); // false; list unchanged

Only the first match is deleted. To delete every copy of a value, use RemoveAll.

Remove by index with RemoveAt

RemoveAt deletes the element at a zero-based position and moves every later element one slot to the left. An index outside the list throws ArgumentOutOfRangeException.

var numbers = new List<int> { 10, 20, 30, 40 }; numbers.RemoveAt(1); // removes 20; list is 10, 30, 40 numbers.RemoveAt(numbers.Count - 1); // removes the last element, 40

RemoveRange(index, count) deletes a block in one call. numbers.RemoveRange(0, 2) deletes the first two elements.

Remove where a condition is true with RemoveAll

RemoveAll takes a predicate, which is a function that returns true for each element to delete. It removes all of them in a single pass and returns how many it removed. This is the C# answer to "remove where".

var numbers = new List<int> { 1, 2, 3, 4, 5, 6 }; int count = numbers.RemoveAll(n => n % 2 == 0); // count is 3; list is 1, 3, 5

The same call removes objects by a property, which is the usual way to remove an object from a list.

record User(string Name, bool IsActive); var users = new List<User> { new("ana", true), new("bo", false) }; users.RemoveAll(u => !u.IsActive); // removes bo

LINQ remove where: Where plus ToList

LINQ has no RemoveAll. A LINQ query reads a sequence and produces a new one, so the pattern is to keep what you want and assign it back.

numbers = numbers.Where(n => n % 2 != 0).ToList(); // keeps the odd numbers

Use RemoveAll when you own the list and want it changed in place. Use Where when the source is an IEnumerable<T>, or when other code holds a reference to the original list and must not see the change.

Remove one list from another

To delete every element that appears in a second collection, combine RemoveAll with Contains. Put the second collection in a HashSet<T> when it is large. Contains on a hash set is O(1), and on a list it is O(n).

var toRemove = new HashSet<int> { 2, 4 }; numbers.RemoveAll(n => toRemove.Contains(n));

numbers.Except(toRemove).ToList() also works, with one difference. Except returns distinct elements, so duplicates in the first list collapse to one copy.

The foreach trap

Calling Remove inside a foreach over the same list throws InvalidOperationException on the next step of the loop. The enumerator records a version number and stops when the list changes under it. Two patterns are safe.

// Wrong: throws InvalidOperationException on the next iteration foreach (var n in numbers) if (n > 3) numbers.Remove(n); // Safe: walk backwards so a removal never shifts an unvisited element for (int i = numbers.Count - 1; i >= 0; i--) if (numbers[i] > 3) numbers.RemoveAt(i); // Best: one call, one pass numbers.RemoveAll(n => n > 3);

A forward for loop compiles and runs, but it skips elements. After RemoveAt(i), the element that was at i + 1 moves to i, and i++ steps over it.

Cost of each method

MethodRemovesCost
Remove(item)First equal elementO(n): a scan, then a shift
RemoveAt(index)Element at indexO(n - index); O(1) for the last element
RemoveAll(predicate)Every matchO(n), one pass
RemoveRange(index, count)A blockO(n)
Clear()EverythingO(n)
Where().ToList()Nothing; builds a new listO(n) time plus O(n) memory

One detail matters for class types. Remove compares with EqualityComparer<T>.Default, which is reference equality unless the class overrides Equals. A new object with the same field values will not match, so remove objects with RemoveAll on a property, or with the reference you already hold. Records, structs and strings compare by value, so Remove works on them as expected.

Key Takeaways

TAGS
Coding Interview
CONTRIBUTOR
Arslan Ahmad
Arslan Ahmad
ex-FAANG engineering manager and author or Grokking series.

GET YOUR FREE

Coding Questions Catalog

Design Gurus Newsletter - Latest from our Blog
Boost your coding skills with our essential coding questions catalog.
Take a step towards a better tech career now!
Explore Answers
Which software is used by network engineer?
What are two limitations of multithreading?
Which algorithm is faster?
What are the tips for coding interviews at biotech companies?
What is a software developer portfolio?
Which website to prepare for Data structures interview questions for freshers?
Related Courses
New
Grokking the AI System Design Interview course cover
Grokking the AI System Design Interview
Learn to design AI systems the way interviewers expect: classic ML products, LLM and RAG architectures, and agentic systems, all through the lens of the system design interview.
4.6
(3,192 learners)
Discounted price for Your Region

$99

Grokking the Coding Interview: Patterns for Coding Questions course cover
Grokking the Coding Interview: Patterns for Coding Questions
The 24 essential patterns behind every coding interview question. Available in Java, Python, JavaScript, C++, C#, and Go. The most comprehensive coding interview course with 543 lessons. A smarter alternative to grinding LeetCode.
4.6
Discounted price for Your Region

$197

Grokking Modern AI Fundamentals course cover
Grokking Modern AI Fundamentals
Master the fundamentals of AI today to lead the tech revolution of tomorrow.
4.1
Discounted price for Your Region

$72

Design Gurus logo
One-Stop Portal For Tech Interviews.
Copyright © 2026 Design Gurus, LLC. All rights reserved.