Skip to Content
Course content

180: List<T> Members In Depth

Click on the "Edit" button in the top corner of the screen to edit your slide content.

By now, you're probably comfortable adding items to a list and looping through them. But if you look at the List<T> class in the documentation, there are dozens of methods you probably haven't touched yet. I've found that most developers stick to Add() and Remove() for far too long, missing out on tools that make the code cleaner and more performant.

What is the actual difference between Count and Capacity?

This is one of those things that doesn't matter until your app starts lagging. Count is the number of elements currently in your list. Capacity is the number of elements the internal array can hold before it needs to resize.

Here is the deal: List<T> is just a wrapper around a standard array. When that array fills up and you call Add(), C# has to allocate a new, larger array (usually double the size) and copy everything over. If you're adding 100,000 items to a list, that happens a lot, and it's expensive.

// If I know I'm loading 10,000 enemies from a save file...
var enemies = new List<Enemy>(10000); 
// I just set the Capacity to 10,000 immediately.
// No resizing happens as I fill it up.

I usually only worry about this in performance-critical paths, but it's a great habit to set the capacity if you have a rough idea of the final size.

Why use FindAll instead of just writing a foreach loop?

You can definitely use a foreach loop and a temporary list to filter data, but FindAll lets you do it in one line using a predicate (a lambda expression). It's much more expressive.

Imagine we have a list of GameEnemy objects and we only want the ones that are currently "Elite" types. Instead of this:

var elites = new List<GameEnemy>();
foreach (var e in allEnemies) {
    if (e.Type == EnemyType.Elite) elites.Add(e);
}

Do this:

var elites = allEnemies.FindAll(e => e.Type == EnemyType.Elite);

It's cleaner, it's faster to read, and it reduces the surface area for bugs. Similar logic applies to Find(), which just returns the first match it hits, or Exists(), which returns a simple true/false.

How do I remove multiple items without crashing the loop?

If you've tried to Remove() an item from a list while iterating over it with a foreach loop, you've probably seen the InvalidOperationException. C# doesn't let you modify the collection while you're walking through it.

The "old school" way to fix this was to loop backwards using a for loop, but that's clunky. The professional way to handle this is RemoveAll(). It takes a predicate and purges everything that matches it in one go.

// Let's say we want to clear out all enemies whose health has hit 0
allEnemies.RemoveAll(e => e.Health <= 0);

I love RemoveAll because it's atomic from your perspective. You don't have to manage indices or temporary "to-be-deleted" lists. It just happens.




📋 Practical Task

Exercise: Managing the Horde

You are building a combat manager for a game. You have a list of Enemy objects (each with a Name, Health, and IsBoss property). Your task is to implement the following logic using the List<T> members discussed in this lesson:

  • Initialize a list with an initial capacity of 50.
  • Use FindAll to create a sub-list of all enemies that are Bosses.
  • Use RemoveAll to instantly delete all enemies from the main list whose Health is 0 or less.
  • Use Exists to check if there are any enemies left in the list and print "Area Clear" or "Enemies Remain" to the console.

Ensure you use lambda expressions for the predicates to keep your code concise.

Rating
0 0

There are no comments for now.

to be the first to leave a comment.