C# List Generic Collection Tutorial

In this tutorial lesson we learn about complex generic data containers that store elements of the same type called lists.

We cover defining and initializing a list, how to access and modify elements via the indexer or loops, how to add elements with the Add and AddRange() functions, how to remove elements as well as counting how many elements exist in a list.

What is a list

A list in C# is similar to an array, in the sense that it’s used to store a collection of data elements of the same type.

Where an array has a fixed size, a list has a dynamic size. We use a list when we don’t know ahead of time how many objects will be stored.

The list namespace

Lists, as a generic collection, is defined in the System.Collections.Generic namespace, so before we can use lists, we must specify the namespace at the top of the document.

Example:
using System;
using System.Collections.Generic;

Now lists will be available to us for use.

How to define a list

We must create a list object with the new keyword to initialize a new instance of the List class. A list is also a generic type, as indicated by the angle brackets, and requires a property.

Syntax:
type identifier = new List<type>();

In the case of a list, the generic property is a type.

Example:
using System.Collections.Generic;

namespace Lists
{
    class Program
    {
        static void Main(string[] args)
        {
            var numbers = new List<int>();
        }

    }
}

In the example above, we create a list of ints and store it in the variable numbers.

How to initialize a list

If we know ahead of the time, the objects that we want to store inside the list, we can use the initialization syntax.

We give the list definition a code block, and specify our values in it, separated by a comma.

Syntax:
type identifier = new List<type>() { values };
Example:
using System.Collections.Generic;

namespace Lists
{
    class Program
    {
        static void Main(string[] args)
        {
            var numbers = new List<int>() { 1, 2, 3, 4, 5 };
        }

    }
}

In the example above, we initialize a new list of numbers with the values 1 through 5.

How to access a single list element with the indexer

We access a single value in a list by using its index. The index number is specified between open and close single brackets.

Syntax:
identifier[index];
Example:
using System;
using System.Collections.Generic;

namespace Lists
{
    class Program
    {
        static void Main(string[] args)
        {
            var message = new List<string>() { "Hello", "World" };

            Console.WriteLine(message[0]);
            Console.ReadLine();
        }

    }
}

In the example above, we access the first element of the list, at index 0, which is the word “Hello”.

How to access multiple list elements with a loop

Because we don’t necessarily know how many elements a list has, we can use the foreach loop to go through each element until it reaches the end.

Example:
using System;
using System.Collections.Generic;

namespace Lists
{
    class Program
    {
        static void Main(string[] args)
        {
            var numbers = new List<int>() { 1, 2, 3, 4 };

            foreach (var i in numbers)
                Console.WriteLine(i);

            Console.ReadLine();
        }

    }
}

How to add values to a list with Add()

Because a list is dynamic in size, we need a way to add values to it. We can do this with the Add() function.

Syntax:
listIdentifier.Add(value);

The Add() function will add a value to the end of the list.

Example:
using System;
using System.Collections.Generic;

namespace Lists
{
    class Program
    {
        static void Main(string[] args)
        {
            var numbers = new List<int>() { 1, 2, 3, 4 };

            numbers.Add(5);

            foreach(var i in numbers)
                Console.WriteLine(i);

            Console.ReadLine();
        }

    }
}

In the example above, we add the number 5 at the end of the list. When we run the example, the number 5 is printed to the console.

How to add multiple values to a list with AddRange()

If we want to add multiple values to a list, we use the AddRange() function.

The AddRange() function accepts an array, or list, or values.

Syntax:
listIdentifier.AddRange( array/list of values );
Example:
using System;
using System.Collections.Generic;

namespace Lists
{
    class Program
    {
        static void Main(string[] args)
        {
            var numArr = new int[5] { 5, 6, 7, 8, 9 };
            var numbers = new List<int>() { 1, 2, 3, 4 };

            numbers.AddRange(numArr);

            foreach (var i in numbers)
                Console.WriteLine(i);

            Console.ReadLine();
        }

    }
}

In the example above, we declared an array of numbers, and then added them to the list.

We can add an array inline, directly inside the AddRange() function’s parameter list.

Example:
using System;
using System.Collections.Generic;

namespace Lists
{
    class Program
    {
        static void Main(string[] args)
        {
            var numbers = new List<int>() { 1, 2, 3, 4 };

            numbers.AddRange(new int[5] { 5, 6, 7, 8, 9 });

            foreach (var i in numbers)
                Console.WriteLine(i);

            Console.ReadLine();
        }

    }
}

Because we initialize the array inline in the AddRange() function’s parameter list, it’s not terminated by a semicolon.

Get the index of a value with IndexOf()

If we need to know the index (position) of a particular value in our list, we can use the IndexOf() function.

Syntax:
identifier.IndexOf(searchValue);
Example:
using System;
using System.Collections.Generic;

namespace Lists
{
    class Program
    {
        static void Main(string[] args)
        {
            var message = new List<string>() { "Hello", "there", "world" };

            Console.WriteLine(message.IndexOf("there"));
            Console.ReadLine();
        }

    }
}

In the example above, the word we’re looking for exists. In the case that a value does not exist in a list, the function will return a value of -1.

Example:
using System;
using System.Collections.Generic;

namespace Lists
{
    class Program
    {
        static void Main(string[] args)
        {
            var message = new List<string>() { "Hello", "there", "world" };

            Console.WriteLine(numbers.IndexOf("Goodbye"));

            if (message.IndexOf("Goodbye") < 0)
                Console.WriteLine("Value does not exist");

            Console.ReadLine();
        }

    }
}

In the example above, the IndexOf() function will return -1 because it can’t find the word Goodbye. We also create an if statement to handle such an error in a meaningful way instead of just displaying -1.

How to remove a value from a list

If we need to remove a value from the list, we can use the Remove() function.

Syntax:
listIdentifier.Remove(value);
Example:
using System;
using System.Collections.Generic;

namespace Lists
{
    class Program
    {
        static void Main(string[] args)
        {
            var message = new List<string>() { "Hello", "there", "world" };

            message.Remove("there");

            foreach (var i in message)
                Console.WriteLine(i);

            Console.ReadLine();
        }

    }
}

In the example above, we remove the word “there” from the list.

How to see the amount of elements in a list with Count

If we want to know how many elements we have inside the list, we can use the Count property.

Syntax:
listIdentifier.Count;
Example:
using System;
using System.Collections.Generic;

namespace Lists
{
    class Program
    {
        static void Main(string[] args)
        {
            var message = new List<string>() { "Hello", "there", "world" };

            Console.WriteLine("List has {0} elements", message.Count);
            Console.ReadLine();
        }

    }
}

In the example above, we check how many elements the list has and output that number to the console.

How to remove all elements from a list

If we need to remove all elements from the list, we can use the Clear() function. The clear function will only remove the elements from the list, it will not remove the list itself.

Syntax:
listIdentifier.Clear();
Example:
using System;
using System.Collections.Generic;

namespace Lists
{
    class Program
    {
        static void Main(string[] args)
        {
            var message = new List<string>() { "Hello", "there", "world", "there" };

            message.Clear();

            Console.WriteLine(message.Count);
            Console.ReadLine();
        }

    }
}

In the example above, we clear all the elements from the list and then output the Count to the console.

Summary: Points to remember

  • A list is a complex generic data container, used to store multiple elements of the same type.
  • Being a generic type, a list requires that we specify the type of data it will contain between angle brackets.
  • List items can be accessed via the indexer or with loops.
  • We can add one or more values to a list with the Add() and AddRange() functions.
  • To see the index of a value we use the IndexOf() function.
  • The Count property holds the amount of elements stored in a list.