C# Collections Pt2 - Generic Collections
Tags: collections, csharp, tutorial, codenewbie
Published: 2021-11-22 14:01:37

So, we discussed Generic Collections in my previous chapter of this series, so let's dive deep into the different types and how to use them.

The syntax is `List<T>`, `Dictionary<Tkey,TValue>` and so on and as we've said before **T** just stands for placeholder of the type of generic collection you'd like to create.


## Lists
``` c#

//Create a class of objects we'd like to store.
public class Animal
{
    public Animal()
    {

    }
    public int Age { get; set; }
    public string Name { get; set; }
    public int NumberOfLegs { get; set; }
    public string Sound { get; set; }
}

var animals = new List<AnimaL>();
```
There you have it you've just created a new empty list that will contain only `Animal` objects. So how do we fill it with objects, well thats simple and can be done in 2 (two) ways.

```c#

 //Option 1 - During instantiating the list.
var animals = new List<Animal>
{
    new Animal { Name = "Dog", Age =4, NumberOfLegs = 4, Sound = "Bark" },
    new Animal { Name = "Cat", Age =14, NumberOfLegs = 4, Sound = "Meow" },
    new Animal { Name = "Duck", Age =1, NumberOfLegs = 2, Sound = "Quack" },
    new Animal { Name = "Lion", Age =2, NumberOfLegs = 4, Sound = "Roar" }
};

//Option 2 - using the Add() method.

var animals = new List<Animal>();
animals.Add(new Animal { Name = "Dog", Age = 4, NumberOfLegs = 4, Sound = "Bark" });
animals.Add( new Animal { Name = "Cat", Age = 14, NumberOfLegs = 4, Sound = "Meow" });
animals.Add(new Animal { Name = "Duck", Age = 1, NumberOfLegs = 2, Sound = "Quack" });
animals.Add(new Animal { Name = "Lion", Age = 2, NumberOfLegs = 4, Sound = "Roar" });

//usage

var dog = animals[0];
```

However the downside to using lists is retrieving the objects in this fashion, as we aren't always sure what index the item will be at, and this is where Dictionaries can often come in useful.

## Dictionaries - Dictionary<TKey,TValue>

Dictionaries are very useful, and work just like a dictionary that we've all used at school, with a key > value pairing. At school we'll have seen a word (key) and its definition (value), and this is how C# Dictionaries work. We provide it a key, and a value to keep. The value can be any piece of information / object we wish to store. We then use the key to access the record within the collection, instead of an index.

To create a new Dictionary<Tkey,TValue> it's as easy as this:

```c#
var animalDictionary = new Dictionary<string,Animal>(){
    {"Dog",new Animal { Name = "Dog", Age =4, NumberOfLegs = 4, Sound = "Bark" }},
    {"Cat",new Animal { Name = "Cat", Age =14, NumberOfLegs = 4, Sound = "Meow" }},
    {"Duck", new Animal { Name = "Duck", Age =1, NumberOfLegs = 2, Sound = "Quack" }},
    {"Lion",new Animal { Name = "Lion", Age =2, NumberOfLegs = 4, Sound = "Roar" }}
}
//and we can use it like so

var lion = animalDictionary["Lion"];
//or
var lionsSound = animalDictionary["Lion"].Sound;
```

So you can see here we've created a `Dictionary<string,Animal>()`, meaning our key, and thing we can search for quickly is the type of animal as a string, and then the value type is an Animal object.
So when we retrive using a similar index syntax in a list or Array (`[]`) we can specify the key and it'll return the value we stored against it just like a Dictionary we used at school.

## Queues - Queue<T>

Queues work in just the same way as a queue does in everyday life, with a first-in , first-out approach. `Queue<T>` does not implement the ICollection interface like Dictionary and Lists, meaning it doesn't have an Add method. Meaning you cannot add elements to the Queue whilst instantiating, it also means you cannot use the **Add*()** method, instead you use the **Enqueue()** method.

```c#

var restaurantQueue = new Queue<string>();
restaurantQueue.Enqueue("Front of Queue");
restaurantQueue.Enqueue("Second in Line");
restaurantQueue.Enqueue("3rd in Line");
restaurantQueue.Enqueue("Back of the Line");

//loop over the items and print out
foreach(var customer in restaurantQueue){
    Console.WriteLine(customer);
}

```
Queues have so many other uses though, as really all we've done is create  list,and looped over it, so what can we do with a Queue that differs, here are some methods and examples

```c#
Queue<string> restaurantQueue = new Queue<string>();
restaurantQueue.Enqueue("Front of the Queue");
restaurantQueue.Enqueue("Second");
restaurantQueue.Enqueue("Third");
restaurantQueue.Enqueue("At the back of queue");

//Let in the next person at the front of the queue and then they're no longer in the queue
Console.WriteLine($"Allow in and remove from the queue: { restaurantQueue.Dequeue() }");
Console.WriteLine($"Allow in and remove from the queue: { restaurantQueue.Dequeue() }");

//Peek at the first  person in the queue without removing them - maybe the restaurant wants to check something without losing their place 
Console.WriteLine($"Person at the front of the queue is : {restaurantQueue.Peek()}");

//Clear the queue
restaurantQueue.Clear();

//Check if someone is in the queue
var queenInQueue = restaturantQueue.Contains("Queen");
Console.WriteLine($"The queen is in the queue = {queenInQueue}");

```

##Stacks - Stack<T>

Stacks are the opposite of a queue, in that they work on a last-in first-out approach.

```c#

var stack = new Stack<string>();
stack.Push("first");
stack.Push("two");
stack.Push("three");
stack.Push("four");
stack.Push("last");

foreach( string number in stack )
{
    Console.WriteLine(number);
}
//Ouput: last four three two first

```
Again we want to utilise the Stack methods, so like the queue we don't use the **Add()** method, we have a **Push** method instead, and to use and remove instead of **Dequeue()** we have **Pop()**.

```c#
var stack = new Stack<string>();
stack.Push("first");
stack.Push("two");
stack.Push("three");
stack.Push("four");
stack.Push("last");

Console.WriteLine(stack.Pop());
Console.WriteLine(stack.Peek());

//Ouput last four
```

## Other things you can do with collections

### Remove
```c#
var animals = new List<Animal>
{
    new Animal { Name = "Dog", Age =4, NumberOfLegs = 4, Sound = "Bark" },
    new Animal { Name = "Cat", Age =14, NumberOfLegs = 4, Sound = "Meow" },
    new Animal { Name = "Duck", Age =1, NumberOfLegs = 2, Sound = "Quack" },
    new Animal { Name = "Lion", Age =2, NumberOfLegs = 4, Sound = "Roar" }
};

animals.RemoveAt(2); // removes the item at index #2 (Duck)

//Remove an item using the item - say you'd loaded it out but then want to remove it after doing something with it, i.e get its name.
var dog = animals.[0];
var dogsName = dog.Name;
animals.Remove(dog);
```

### Sort Lists, these are available on any collection that implements the IComparable interface

```c#
var animals = new List<Animal>
{
    new Animal { Name = "Dog", Age =4, NumberOfLegs = 4, Sound = "Bark" },
    new Animal { Name = "Cat", Age =14, NumberOfLegs = 4, Sound = "Meow" },
    new Animal { Name = "Duck", Age =1, NumberOfLegs = 2, Sound = "Quack" },
    new Animal { Name = "Lion", Age =2, NumberOfLegs = 4, Sound = "Roar" }
};

animals.Sort((x, y) => x.Name.CompareTo(y.Name));
foreach (var animal in animals)
{
    Console.WriteLine(animal.Name);
}
```
Here we're using the Sort method, which takes in a comparer. In our case we're passing it an anonmous method, that is taking `(x,y)` and it will compare x.Name to y.Name. `Y` is the next element in the list, so it will compare using the default comparer (ascending) for a string, and sort the items in alphabetical order.



## Summary

I hope you have a better understanding of how we can use Generic collections, now go out there and build a console application and start playing with generic collections.
As always if you have any questions, or want updates on upcoming chapters, or just want to communicate with me, don't forget to follow me on twitter at [@Gweaths](https://twitter.com/GWeaths)