Understanding Lists and Dictionaries in C#
[Home] [Writing samples] [LinkedIn]

By Robert Delwood

A lead API documentation writer

Collecting and organizing groups of data in an application is in the realm of arrays and lists. In C# and .NET, this falls to Collections. Collections are a generalized group of data set types that manage groups of information. Understanding Collections in general, the types of lists, and when to use each one makes programming more efficient. This article examines to Collection types: Lists and Dictionaries. Here's where to start.

Keeping track of information in an application is critical. Applications are nothing more than just combining data and algorithms. The trick then, is how best to track that information.

The simplest way is with a variable. The following are ways to track two bits of information, a test score and a name:

var test1 = 5;
var username = "Robert";

But what if we wanted to track multiple values of the same kind of information? For example, we want to track test scores. It would be impractical to have a variable for each test:

var test1 = 95;
var test2 = 91;
var test100 = 83;

For this we can use an array. An array is a sequential set of information. If we knew ahead of time there would be five tests, we could declare:

int[] myTestScores = new int[5];

This creates an array with five positions, indexed with values 0 through 4. If you're new to C#, all counting begins with 0. The days of Basic's Option Base 1 are over. To add scores to the array, use:

myTestScores[0] = 91;
myTestScores[1] = 95;
myTestScores[2] = 96;
myTestScores[3] = 82;
myTestScores[4] = 88;

And then to retrieve a score, do the opposite:

var myScore = myTestScores[0];

In this case, myScore would be set to 91.

Arrays are a part of almost every language. In .NET (as in C#), it is also an object. This means it has methods attached to it. In the Visual Studio editor, entering a dot after the array name shows the method list.

For example, using the Average function, you'd use:


However, arrays are old school. They seem to be included in C# just for backward compatibility. The C# way of doing this is through a Collection item. A Collection is a group of list-related features. The Collection item most related to an array is the List. This is an array but offers much more versatility, speed, and flexibility.

To declare a List, use either:

var myList = new List(); //For an int-based List
var myList = new List(new int[] { 91, 88, 25 }); //If you know some values ahead of time

Notice you didn't have to declare ahead of time how many elements there are. You can add and delete them dynamically. That is, when you need to. For instance:

To add an item:

myList.Add(85); //Adds the value at the end of the list

To delete an item:

myList.RemoveAt(0); //Removes position 0

To find an item:

myList.Find(item=> item == 88);

To sort the list. Sorting reorders the item in place. This means you don't have to assign the result to a new variable. Just making the calls reorders the list.

myList.Sort(); //Ascending order
myList.Reverse(); //Descending order

Some notes about these.

You will absolutely want to search for these on the internet. It's much better to find as exact of samples as possible. Try searches like C# list find item.

There may seem to be an overwhelming number of options for each call. List. The Find method alone has seven variations. Don't get overwhelmed. Use just one call at a time to get used to it. As you get ambitious, then branch out to other variations.

You will often see additional formatting, like List. That's a generic way to specify a list, and the T is a placeholder the list type. If you're working in ints, that translates to List. List is for strings.

Some include predicates. A predicate is a kind of qualifier. An earlier example uses

myList.Find(item=> item == 88);
The last part
((item=> item == 88))
is the predicate. That specifies a condition to meet to return items. In this case, it specifies the value 88 to return. Another way of thinking about this is to say "Find instances where item equals 88." This is a weak example, but can be made as complex as you want. Moving one step beyond:

myList.Find(item=> item > 90);

specifies any values above 90 are returned.


Another common collection is the dictionary. A dictionary is a set of paired entries. A common analogy is, literally, the word dictionary. That is a set of paired entries: A word, and it's meaning. You look an entry by using the word, and the definition is associated with it. A dictionary collection is similar. The first entry of the pair is called the key name, and the second entry is the value. You look up the key to find the value.

You may see a dictionary referenced as Dictionary<TKey, TValue>. The T names are placeholders for actual types. In other words, you need to specify the data type for the two dictionary entries. In the following examples, each entry is a string, the team code, and the full name, and so Dictionary<string, string>. You could change that up a little bit, and instead, want to count the number of occurrences for each team. In that case you would define the dictionary as Dictionary<string, int>. For example, an entry might be <"HOU", 12>. These types don't even have to be atomic data types, like string or int. They can be objects, like DateTime, or a custom one of your own, perhaps like BaseballTeamsStats. The rest of the word is the label for the field. So, TKey is the key name, and TValue is the value field.

To declare a dictionary collection, use:

var sportsTeams = new Dictionary<string, string>();

And to add entries, use:

var sportsTeams = new Dictionary<string, string>();
sportsTeams.Add("HOU", "Houston Astros");
sportsTeams.Add("CHC", "Chicago Cubs");
sportsTeams.Add("BOS", "Boston Red Socks");

Some notes about these.

The important thing to remember about dictionaries are the key name must be unique within the collection. That is, a key name can only be used once. Values can be used any number of times.

You find values by searching the collection for the key name. There is no index position. Many users new to dictionaries will want to find the values by position like they would with a list. Something like sportsTeams[0]. That's not only an error, but also in understanding dictionary collections that doesn't even make sense. There is no zero position.

You use dictionaries in situations where you know the key name is needed only once. For example, you have a product inventory system and track items be part number. You know each part number will be unique, so a dictionary is a good choice. In contrast, an employee tracking system likely will have duplicate names, and so not a good choice for dictionaries.

Dictionary searches are extremely fast.

To add entries use:

if (!sportsTeams.ContainsKey("ATL")) sportsTeams.Add("ATL", "Atlanta Braves");

It is important to check that the key is not already there. That results in an error. Using this code, the key is checked, and if it's not in the dictionary already, it's added.

To retrieve a value:

var myTeam = sportsTeams ["HOU"]

This looks like an index, but it's the key name.

To update an entry:

sportsTeams["HOU"] = "Colt 45s";

To delete an entry:

if (!sportsTeams.ContainsKey("CHC")) sportsTeams.Remove["CHC"];

Again, check to see if the value is there first. Removing an entry that isn't there results in an error.