A Jolly Good Guide to Collections in C#
Tags: tutorial, programming, csharp, dotnet
Published: 2024-06-15 10:03:35

{% embed https://youtu.be/4H0gabAtouE %}.


Ah, collections in C#. It’s a bit like organising your sock drawer, isn't it? You start with a simple array and then realise you need something a bit more sophisticated to handle the chaos. Today, we'll dive into the wonderful world of collections in C# and learn how to keep our code as neat and tidy as possible. So, brew yourself a nice cuppa, sit back, and let's get started! ☕

### The Humble Beginnings: Arrays

In the early days of .NET, we had just arrays. Simple, straightforward, but a bit rigid, like trying to squeeze into those old jeans from uni. Here’s how an array looks in its most basic form:

```csharp
int[] ints = {1, 2, 3};
```

Iterating through an array is a piece of cake with a `for` loop:

```csharp
for (int i = 0; i < ints.Length; i++)
{
    Console.WriteLine(ints[i]);
}
```

However, adding or removing elements? Absolute nightmare. You have to create a whole new array each time. It's like having to buy a new wardrobe every time you get a new pair of socks. Not ideal. So, how do we improve this? Enter **IEnumerator**.

### Enter the Enumerator: IEnumerator

IEnumerator is the hero we need when it comes to iterating through collections without the headache of manually managing the position. It consists of three main parts: `Current`, `MoveNext`, and `Reset`. 

- `Current` points to the current element in the collection.
- `MoveNext` moves to the next element.
- `Reset` resets the position.

Here's a sneak peek at how it works:

```csharp
IEnumerator enumerator = ints.GetEnumerator();
while (enumerator.MoveNext())
{
    Console.WriteLine(enumerator.Current);
}
```

### The Iterable Fellow: IEnumerable

When a collection inherits from **IEnumerable**, it’s saying, "Hey, you can iterate through my elements using an IEnumerator." It’s a read-only interface, meaning you can't add or remove elements directly. It's like a guided tour where you can look but not touch.

```csharp
public class MyCollection: IEnumerable
{
    private int[] _array = {1, 2, 3};

    public IEnumerator GetEnumerator()
    {
        return _array.GetEnumerator();
    }
}
```

### The Collector: ICollection

To address the limitations of IEnumerable, Microsoft introduced **ICollection**. It inherits from IEnumerable and adds functionalities like `Count` and `CopyTo`. However, it still doesn't allow adding or removing items. Think of it as a fancy display case, you can count your collectables, but you can't easily add new ones without some effort.

```csharp
public class MyCollection : ICollection
{
    private List<int> _list = new List<int> {1, 2, 3};

    public int Count => _list.Count;

    public void CopyTo(Array array, int index)
    {
        _list.CopyTo((int[])array, index);
    }

    public IEnumerator GetEnumerator()
    {
        return _list.GetEnumerator();
    }
}
```

### The All-Rounder: IList

Now, **IList** comes into play, inheriting from `ICollection` and allowing us to add, remove, and access elements by index. It's the Swiss Army knife of collections – versatile and handy for all sorts of tasks.

```csharp
public class MyCollection : IList
{
    private List<int> _list = new List<int> {1, 2, 3};

    public int this[int index] 
    { 
        get => _list[index]; 
        set => _list[index] = value; 
    }

    public void Add(int value)
    {
        _list.Add(value);
    }

    public void Remove(int value)
    {
        _list.Remove(value);
    }

    // Other IList members...
}
```

### Generic Delight: IList<T>

The DotNet team also introduced generics to these interfaces for type safety and flexibility. With `IList<T>`, you can create collections that are type-specific, avoiding those pesky runtime errors.

```csharp
List<int> list = new List<int> {1, 2, 3};
list.Add(4);
Console.WriteLine(list[0]);
```

### The Trusty Dictionary: IDictionary

Lastly, there's **IDictionary**, which allows storing key-value pairs. Perfect for those times when you need to organise your data more efficiently.

```csharp
IDictionary<int, string> dictionary = new Dictionary<int, string>
{
    {1, "One"},
    {2, "Two"},
    {3, "Three"}
};
```

### Summary

To sum it up, collections in C# have evolved from simple arrays to more sophisticated structures like IEnumerable, ICollection, and IList, with generics adding even more power and flexibility. These tools help us write cleaner, more efficient code. Remember, choosing the right collection can make your code easier to manage and more efficient. So, explore these options and find the best fit for your needs.

If you've got any thoughts or funny coding anecdotes to share, drop a comment below. Let's keep the conversation going! 

And remember, keep calm and code on! 😄👨‍💻👩‍💻