CodeBlanks Logo Icon CodeBlanks

Custom collection

C# course · Intermediate · Lesson 85/116

Learn to write your own IEnumerable<T> collection.

Write your own collection

Implement IEnumerable<T> on a class and it gains foreach support. The simplest path is to hold an inner List<T> and route GetEnumerator to it.

Example: class NumberBag : IEnumerable<int>. Add an Add method; in GetEnumerator return _items.GetEnumerator(). Now you can write foreach (var n in bag).

How to write GetEnumerator

IEnumerable<T> demands two GetEnumerator methods: a generic one returning IEnumerator<T> and a non-generic one returning IEnumerator. Routing both to the inner list is easiest.

The non-generic version is for legacy foreach compatibility. The signature: IEnumerator IEnumerable.GetEnumerator() => _items.GetEnumerator();. When both methods route to the same inner list, the collection is ready.

Exercise Write a NumberBag collection

The NumberBag class below implements IEnumerable<int> but lacks GetEnumerator. Add the generic GetEnumerator method returning _items.GetEnumerator(). In Main iterate with foreach and print each item.

Show example solution
Write public IEnumerator<int> GetEnumerator() { return _items.GetEnumerator(); }. In Main add foreach (var n in bag) Console.WriteLine(n);.
Example solution:
using System;
using System.Collections;
using System.Collections.Generic;

class NumberBag : IEnumerable<int>
{
    private List<int> _items = new List<int>();

    public void Add(int n) => _items.Add(n);

    public IEnumerator<int> GetEnumerator()
    {
        return _items.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator() => _items.GetEnumerator();

    static void Main()
    {
        var bag = new NumberBag();
        bag.Add(1);
        bag.Add(2);
        bag.Add(3);
        foreach (var n in bag)
        {
            Console.WriteLine(n);
        }
    }
}

Test yourself

  1. Which interface for foreach?

    • IDisposable
    • IClonable
    • IComparable
    • IEnumerable<T>
    Show answer

    IEnumerable<T> — Correct. A class implementing IEnumerable<T> can be iterated with foreach.

  2. Implement the interface

    class NumberBag : IEnumerable<____>
    Show answer
    class NumberBag : IEnumerable<int>
  3. Match the part to its role

    Add
    Adds an item
    GetEnumerator
    Returns iterator
    _items
    Inner list
    IEnumerable<T>
    Iteration contract

All lessons in Intermediate