Lists

Less Pain == More Fun

Alphabet Soup

The List class is part of the C# System Collections Framework, which real people generally call "Collections".

We use List as a tool to make dealing with sequences or collections of things easier. It offers us an abstraction to do away with fiddling about with arrays. We're going to contrast using List with using arrays.


Arrays are fixed size

We can't change the size of an array once we've created it. It will never grow or shrink. This array will always have a Length of three:

int[] threeThings = new int[3];

If I wanted to add a 4th element to this array, I would be forced to do something like this:

int[] myArray = { 1, 2, 3 };
int[] arrayTwo = new int[4];
for (int i = 0; i < arrayTwo.Length; i++)
{
  arrayTwo[i] = myArray [i];
}

myArray[4] = 42;

We are forced to create a new array and assign it the values of our myArray variable. Imagine if we needed to insert a new element in the middle? Yuck!


Lists can grow and shrink

List is a standard class, so we create an instance of it just like any class we'd create:

List<string> giantWords = new List<string>();
giantWords.Add("fee");
giantWords.Add("fie");
giantWords.Add("foe");
Console.WriteLine(giantWords);
Console.WriteLine("my list has " + giantWords.Count + " elements");

giantWords.Add("fum");
Console.WriteLine(giantWords);
Console.WriteLine("my list has " + giantWords.Count + " elements");

I'm not even forced to specify the size! The Count property tells me how big my list currently is.

If you run this code, you'll also see that List also gives us a better String representation than arrays did. (It does this in its ToString method. All classes have one.)

Something there looks strange, though, eh?


Generic Types

The syntax for our declaration and initialization probably looks a bit funky at first:

List<string> giantWords = new List<string>();

One would read this as "a List of Strings named giantWords".

List is a generic type, List<string> is a parameterized type, and giantWords is an instance of parameterized type. Here, that type is String.

What does this mean? When we declare a List, we also declare what type of things it will hold. We can only add Strings to this List.


Objects like any other

The way we use Lists is the same as we would use any other class. We create an instance of it, then we call methods (send messages) to ask it to modify itself or give us information.


How big is it?

We've already seen the Count property in use. It corresponds to Length for an array.

To check whether an array is empty, we would compare its Length to zero:

if(myArray.Length == 0) {
  Console.WriteLine("I'm empty!");
}

Do you have one of these?

If we wanted to check whether an array contained an element, we would iterate over it, checking each element:

string[] myTools = { "hammer", "shovel", "wrench" };
foreach (string tool in myTools)
{
  if (tool.Equals("hammer"))
  {
    Console.WriteLine("I have a hammer!");
  }
}

List has a Contains method for this:

List<string> myTools = new List<string>();
myTools.Add("hammer");
myTools.Add("shovel");
myTools.Add("wrench");

if(myTools.Contains("hammer")) {
  Console.WriteLine("I have a hammer!");
}

Where is it?

If I want to know the index of an element in an array, it's a bit painful:

string[] myTools = { "hammer", "shovel", "wrench" };
for(int index = 0; index < myTools.Length; index++) {
  if(myTools[index].Equals("shovel"))
  {
	  Console.WriteLine("Shovel is element " + index);
  }
}

With a List, we have the IndexOf method:

List<string> myTools = new List<string>();
myTools.Add("hammer");
myTools.Add("shovel");
myTools.Add("wrench");

Console.WriteLine("Shovel is element " + myTools.IndexOf("shovel"));

Look, ma! No curly brackets!


Order is important

Lists remember the order in which you Add elements. Other types of collections don't care so much, but order is one of the intrinsic properties of a list. Try running this code, then changing the order of the Add calls and running it again:

List<string> giantWords = new List<string>();
giantWords.Add("fee");
giantWords.Add("fie");
giantWords.Add("foe");
Console.WriteLine(myList);

Loopy again

Like arrays, a List is iterable, so we can use the enhanced for loop with it:

List<string> giantWords = new List<string>();
giantWords.Add("fee");
giantWords.Add("fie");
giantWords.Add("foe");

foreach(string word in giantWords) {
  Console.WriteLine(word + "! ");
}

More Tools

List has a number of other useful methods. The examples assume our list was created like so:

List<string> myThings = new List<string>();
myThings.Add("this");
myThings.Add("that");
myThings.Add("the other");

Here are some other methods we can use:

method example what it does
Clear() myThings.Clear(); removes all the elements
Insert(int index, string element) myThings.Insert(1, "foo"); assigns "foo" to index 1, replacing "that":
"this", "foo", "the other"
Add(int index, string element) myThings.Add(1, "foo"); inserts "foo" at index 1, shifting the others down to make room:
"this", "foo", "that", "the other"
RemoveAt(int index) myThings.RemoveAt(1); removes the element at index 1:
"this", "the other"
Remove(string element) myThings.Remove("that"); removes the value from the list:
"this", "the other"

Exploring Lists

As you move into exercises, you'll be inclined to dig into the List class. You might not find what you expect. As part of the Collections framework, List is just one piece of the puzzle. You'll find that some of the methods we're using aren't even in List!


A method by any other name…

Notice the convention we're seeing with methods. It's a good one to follow when you create your own methods. Generally, a method should be doing something or giving us information, not both. It's a good practice to use verbs for methods that do things (public void Quit()), and VerbNoun for method names for methods that give us things (for example: public int CalculateAgeInYears() {}) It is also common to see methods whose names start with get or is that give us information.


Not all bad

When might we use an Array rather than a List?


Do It!

  • Create a List. Add five animals to your list. Print each animal in your list.

  • Create a list that contains the following boolean values: true, false, false, true, false. Loop through your list. Based on the value of each element, print a message:

    • true: "Better bring an umbrella"
    • false: "No rain today, enjoy the sun!"
  • Create a list with the following numbers: 1, 23, 9, 77, 922, 6, 32, 63, 14, 5, then: - determine whether each of the following values is an element in the list: 23, 77, 15 - remove the following elements: 23, 922, 32, 6 - again determine whether each of the following values is an element in the list: 23, 77, 15 (Stretch: create a method so that you don't need to duplicate this work.)

  • Come up with an example of how you might use each of the methods from the "More Tools" slide.