DEV Community

Cover image for Data Structures in C# Part 2: Lists <T>
Rasheed K Mozaffar
Rasheed K Mozaffar

Posted on • Updated on

Data Structures in C# Part 2: Lists <T>

Hey There 👋🏻

In part 1 of this series, I talked about arrays, which are cool and provide amazing functionality, and to extend on the data structures that you the developer could use, we'll be learning the generic lists in C#, which is an essential data structure that any C# developer should have at their disposal.

So, Let's begin 🚀

What is a list in C#?
Lists in C# are a type of the generic collections that can be used to store objects of the same data type which then can be accessed through their indexes. Well, how are they any different from arrays that we discussed in part 1 you may ask?

Good question.
The answer is pretty simple! Lists are dynamic, meaning that they could grow and shrink, whereas arrays have fixed a size which is assumed to be known by the developer in the moment of creating the array.

How do we create a list?
Creating a new list is pretty straightforward, let's have a look at a couple of ways:


List<string> values = new();
List<string> values = new List<string>();
var values = new List<string>();

Enter fullscreen mode Exit fullscreen mode

In the previous code, I showed the 3 ways in which we could declare a new list with the name value that will store string values.

You can use whichever syntax you like, it's a subjective preference and has nothing to do with correctness or the like.

In the previous code, we declared a new list of strings, but we haven't provided it with any values. The following code block shows how values are initially added to a list immediately after declaration:


List<string> values = new()
{
    "Value1" , "Value2" , "Value3,
};

Enter fullscreen mode Exit fullscreen mode

In this snippet, I created the values list and I added 3 elements to it, elements are comma separated.

NOTE: We could've done the declaration in a step, and the initialization in a separate step, but it's more convenient this way since I knew what values will be seeded in advance.

How to access elements in a list?
We can access elements the same way we did with arrays, through the index of an element, again, lists are zero-indexed, just like arrays.

The next code snippet prints the final value in the list:


Console.WriteLine(values[2]);
//OUTPUT: Value3

Enter fullscreen mode Exit fullscreen mode

To update an element, we can easily just use its index and provide it a new value, just like the following:


values[0] = "New Value At 0";
Console.WriteLine(values[0]);
//OUTPUT: New Value At 0

Enter fullscreen mode Exit fullscreen mode

That simple!

Let's see the dynamic features of Lists

As I said previously, one key point that makes lists differ from arrays is their dynamic nature. Let's look at some methods and properties of the generic list so we can see its dynamism in action.

List.Add();: This method adds a new element to the list, the element has to of course be of the same type as the type you choose when you first create the list.


List<int> numbers = new();

for(int i = 1; i <= 10; i++)
{
    numbers.Add(i);
}

Enter fullscreen mode Exit fullscreen mode

The previous code creates a new list of integers and uses a for loop to add the numbers from 1 to 10 to our numbers list.

List.Remove();: This method is contrary to the first one, it removes an item from the list, let's see how we can remove an element that we added to our numbers list:


numbers.Remove(5);

Enter fullscreen mode Exit fullscreen mode

After this removal, I can use a foreach loop to print out all the numbers in the numbers list, just as follows:


foreach(int number in numbers)
{
    Console.Write($"{number}\t");
}
//OUTPUT: 1       2       3       4       6       7       8       9       10

Enter fullscreen mode Exit fullscreen mode

And as you can see, the 5 is missing in the sequence.

List.Count: This property is equivalent to Array.Length, it returns the number of elements in a list, it's particularly useful if you want to use a for loop.

List.Capacity;: This property gets or sets the overall number of elements that the list can hold without having to resize itself. If you create a list with one element, and you print out its capacity, you will see 4 is printed out, that means the list can now accommodate 4 elements before it has to resize and expand itself, similarly, the capacity will be brought down if elements are being removed from the list.

💡Pro Tip: If the number of elements that will go inside the list is known beforehand, then set its capacity to that number so it improves performance. Say you want a list with only 2 items, by setting the capacity to 2, the list won't make it 4 automatically, thus gaining some bits and pieces in performance here and there, but don't worry that much about it, computers are fast enough these days to handle those small margins.

How to search for an element in a list?

Assuming we're looking for the index of a particular value in our list, how do we get it? It could be done manually by looping over the elements of the list and then comparing each individual value to the target value that we want its index. However, there'a much easier way by using the FindIndex Method. Let's see that in code:


List<int> numbers = new() {5 , 10 , 15 , 20 , 25};
int indexOfTen = numbers.FindIndex(index => index == 10);

Console.WriteLine($"The index of the number 10 is: {indexOfTen}");
//OUTPUT: The index of the number 10 is: 1

Enter fullscreen mode Exit fullscreen mode

In this snippet, I created a new numbers list and initialized it with 5 values, then I declared a new variable with the name indexOfTen, I assigned it to the returned value from the FindIndex() method, for its argument, I passed a Lambda Expression, which is like a condition, if the condition is true, then we want to return the index of the first value that evaluated our condition to true, this thing is called a predicate, which is a delegate, but that's not what we're here for.

💡Pro Tip: Lists and most collections in C# couple extremely well with LINQ, Language INtegrated Query which is a very powerful feature of C#, if you're interested in learning the basics of it, I have a full post where I provided tons of practical examples, you can find the post's link at the end of this post.

List.Find();: This method returns the value provided if found, otherwise, the default value of the data type that the list is storing, 0 for value types, null for reference types. This method is used heavily while doing data access, and for that reason, I want to show you a practical example that involves searching for a particular object inside a list.

For this example, I'll create a class, and call it Superhero with only 2 properties, an ID and a Full Name, you can see its code below:


public class Superhero
{
    public int Id { get; set; }
    public string FullName { get; set; }
}

Enter fullscreen mode Exit fullscreen mode

That's our class sorted, let's create a list of super heroes:


List<Superhero> heroes = new()
{
    new Superhero {Id = 1, FullName = "Tony Stark"},
    new Superhero {Id = 2, FullName = "Peter Parker"},
    new Superhero {Id = 3, FullName = "Steve Rogers"}
};

Enter fullscreen mode Exit fullscreen mode

I declared a list called heroes that stores objects of type Superhero, then I initialized it with 3 objects, each with their respectively unique ID. Now, I want to find if there's a hero with the ID 2, if so, I want to print out their name, let's see that in code:


Superhero heroWithIdTwo = heroes.Find(hero => hero.Id == 2);

if (heroWithIdTwo != null)
{
    Console.WriteLine($"The hero with ID 2 is called: {heroWithIdTwo.FullName}");
//OUTPUT: The hero with ID 2 is called: Peter Parker
}

Enter fullscreen mode Exit fullscreen mode

All I'm doing here is looking through my list of heroes, to check if there's a hero with 2 as their ID, which I know in advance that there's a hero with this ID, in a real scenario, you would want to throw an exception and catch it so that you could return some error message to the user saying that an object with the given ID doesn't exist, but that's not related to what we're learning in this series.

👾 And There you have it 👾

You've learned how to use the generic list in C#, which is absolutely Brilliant, if I could leave you with a final piece of advice, it has to be me telling you to play around with this data structure, as it's extremely powerful and used everywhere, and even though it seemed like we covered a lot in this post, we've barely scratched the surface, but still, you're ready to take what we've learned and experiment on your own, and before you go, check the LINQ post so that you get some hands on experience with a great companion for lists and most other data structures in C#.

Bye for now 👋🏻

Learn LINQ here: 👉 https://dev.to/rasheedmozaffar/basics-of-linq-in-c-with-examples-2dgi

Top comments (0)