C# List Clear: How to Empty a List in C#
c# list clear: Learn how to use List<T>.Clear() to remove all elements from a C# list, including performance implications, alternatives, and common pitfalls.
c# list clear requires a clear understanding of the core syntax, runtime behavior, and practical implementation patterns demonstrated in the examples below.
The List<T>.Clear() method is the standard way to remove all elements from a List<T> in C#. It sets the Count property to zero and releases references to the stored objects, but it does not necessarily shrink the internal array that backs the list. This distinction matters for both performance and memory usage in long-running applications.
What List<T>.Clear() Does
List<T>.Clear() is an instance method defined on List<T>. It removes every element from the list, leaving Count at zero. The method returns void and does not throw an exception unless the list itself is null. Here is the basic usage:
List<string> names = new List<string> { "Alice", "Bob", "Charlie" }; names.Clear(); Console.WriteLine(names.Count); // Output: 0
After calling Clear(), the list is empty and ready for new elements. The internal array capacity remains unchanged, so if you had added many items, the list still holds that allocated memory. This is an important behavioral detail when you are working with large collections.
Clearing vs. Reassigning a New List
A common alternative to Clear() is to assign a new List<T> instance to the variable:
names = new List<string>();
This also results in an empty list, but the original list object becomes eligible for garbage collection if no other references exist. The choice between Clear() and reassignment depends on whether other code holds a reference to the original list. If you pass the list to another method or store it in a field, reassigning the variable does not affect those other references. Clear() modifies the same instance, so all references see the emptied list.
Consider this scenario:
List<int> sharedList = new List<int> { 1, 2, 3 }; ProcessList(sharedList); // This method might store the reference somewhere sharedList.Clear(); // The stored reference also sees an empty list
If you reassign sharedList instead, the stored reference still points to the old list with its three elements. This is the primary reason to prefer Clear() when you need to reuse the same list instance.
Performance and Memory Implications
Clear() runs in O(n) time because it must release references to each element. For value types, it simply overwrites the internal array slots with default values. For reference types, it sets each slot to null, allowing the garbage collector to reclaim the objects if no other references exist.
The method does not reset the internal Capacity property. If you clear a list that previously held thousands of items, the backing array remains allocated. If you then add a small number of items, the list continues to use that large array. This can waste memory if the list is cleared and then kept small for a long time.
If memory usage is a concern, you can call TrimExcess() after Clear() to shrink the capacity to the actual count (which is zero). However, this forces a new allocation and copies zero elements, so it is only useful when you know the list will stay small for an extended period.
names.Clear(); names.TrimExcess(); // Capacity becomes 0
Keep in mind that calling TrimExcess() after every Clear() can hurt performance if you frequently add and remove many items, because it defeats the purpose of capacity reuse.
Common Mistakes and Edge Cases
One common mistake is calling Clear() on a null reference. List<T> is a reference type, so if the variable is null, calling Clear() throws a NullReferenceException. Always ensure the list is initialized before clearing it.
Another edge case is clearing a list while iterating over it. The List<T> enumerator does not support modifications during enumeration. If you try to call Clear() inside a foreach loop, you will get an InvalidOperationException because the collection changed. Instead, collect the items you want to remove and clear after the loop, or use a for loop that goes backward.
// This throws InvalidOperationException foreach (var item in list) { list.Clear(); }
If you need to conditionally clear the list based on element properties, consider using RemoveAll with a predicate, which removes only matching elements and is safe to call directly.
Alternatives to Clear(): RemoveAll and Count = 0
List<T>.RemoveAll(Predicate<T>) removes all elements that match a condition. It is more flexible than Clear() when you only want to remove a subset. However, if the predicate always returns true, it effectively clears the list, but it does so by shifting elements, which is less efficient than Clear().
Another way to empty a list is to set the Count property directly to zero:
list.Count = 0;
This works because List<T> exposes a public setter for Count. It behaves similarly to Clear() in that it removes all elements and leaves capacity unchanged. However, Clear() is more explicit and self-documenting, so it is generally preferred for readability.
The following table compares the three approaches:
| Approach | Removes All Elements | Releases References | Capacity Reset | Readability |
|---|---|---|---|---|
Clear() | Yes | Yes | No | High |
Count = 0 | Yes | Yes | No | Medium |
RemoveAll(true) | Yes | Yes | No | Low |
Clear() is the clearest and most direct method for emptying a list. The other options are useful only in specific contexts.
When to Use Clear() vs. Alternatives
Use Clear() when you want to reuse the same list instance and need all references to see the emptied list. This is common in pooling scenarios or when a list is stored as a field and reused across requests.
If you are the only owner of the list and no other references exist, reassigning a new list can be simpler and may allow the old list to be garbage collected. This is often the case in local variables or when the list is short-lived.
Use RemoveAll when you need to remove only elements that satisfy a condition, not the entire list. And avoid setting Count = 0 unless you have a specific reason, because it is less readable than Clear().
Clearing a List in Concurrent Scenarios
List<T> is not thread-safe. If multiple threads access the same list and one thread calls Clear(), other threads may see inconsistent state or throw exceptions. If you need to clear a list from multiple threads, use a lock or a concurrent collection like ConcurrentBag<T> or ConcurrentQueue<T>, depending on your access pattern.
For example, if you have a shared list that is populated by one thread and cleared by another, you must synchronize access:
private readonly object _lock = new object(); private List<int> _items = new List<int>(); public void ClearItems() { lock (_lock) { _items.Clear(); } }
Even reading Count after a concurrent Clear() can be problematic. Use proper synchronization or switch to a thread-safe collection that matches your usage.
This covers the essential aspects of c# list clear. The method is straightforward, but understanding its memory behavior and the implications for shared references helps you avoid subtle bugs in production code.