Skip to content

IEnumerable and IEnumerator

Become a developer with our complete learning paths
Become a developer with our complete learning paths

Introduction

The IEnumerable interface is the base Interface for many collections in C#, and its job is to provide a way of iteration through a collection. That is why we can use for each loops to go through a List or a Dictionary. In simple English when a collection class implements the IEnumerable interface it becomes countable, and we can count each element in it individually

There are 2 versions of the IEnumerable Interface

1.IEnumerable <T> for generic collections

2.IEnumerable for nongeneric collections

But since generic collections were introduced later after the non-generic ones and it is no longer recommended to use the non-generic collections in a new project due to their need to perform boxing and unboxing (converting the types of objects), we will explain how to use the

IEnumerable <T> interface in this lesson

IEnumerable<T> contains a single method that you must implement when implementing this interface; GetEnumerator(), which returns an IEnumerator<T> object. The returned IEnumerator<T> provides the ability to iterate through the collection by exposing a Current property that points at the object we are currently at in the collection.

IEnumerables have a method to get the next item in the collection, so they look at items “one at a time,” they don’t need the whole collection to be in memory. They don’t know how many items are in it for each loop. It just keeps getting the next item until it runs out. IEnumerables also help ensure immutability (read-only)

when it is recommended to use the IEnumerable interface:

  • Your collection represents a massive database table, you don’t want to copy the entire thing into memory and cause performance issues in your application.

When it is not recommended to use the IEnumerable interface:

  • You need the results right away and are possibly mutating/editing the objects later on. In this case, it is better to use an Array or a List

Making your Classes Enumerable

In this example, we will see how to make our class Enumerable meaning we can use an instance of it inside a for each loop

let’s consider the following classes

Class 1: a class called dog which has two properties

  1. string Name
  2. bool IsNaughtyDog

and one method

  1. GiveTreat() which will cause the dog to say “wuf” on the console :)
//a class named Dog which we will use in another class called DogShelter which will contain a collection of this class
class Dog {
				//the name of the dog
        public string Name { get; set; }
        //is this a naughty dog
				public bool IsNaughtyDog { get; set; }
				//simple constructor 
        public Dog(string name,bool isNaughtyDog) {
            this.Name = name;
            this.IsNaughtyDog = isNaughtyDog;

        }
				//this method will print how many treats the dog received 
        public void GiveTreat(int numberofTreats) {
						//print a message containing the number of treats and the name of the dog
            Console.WriteLine("Dog: {0} said wuoff {1} times!.", Name, numberofTreats);
            
        }
    }

Class 2: a class called DogShelter

Which contains the List of dogs and that’s it

The List of dogs is initialized in the constructor

//a class named DogShelter this class contains a generic collection of type Dog
//objects of this class can't be used inside a for each loop because it lacks an implementation of the IEnumerable interface
class DogShelter {
				//list of type List<Dog>
        public List<Dog> dogs;
				//this constructor will initialize the dogs list with some values
        public DogShelter() {
            //initialize the dogs list using the collection-initializer
						dogs = new List<Dog>() {
                new Dog("Casper",false),
                new Dog("Sif",true),
                new Dog("Oreo",false),
                new Dog("Pixel",false),
            };
        }
}

Now in the main method let’s create a new DogShelter object and try to Enumerate through it

using a for each loop

using System;
using System.Collections.Generic;

namespace IEnumerableandIEnumerator {

    class Program {

        static void Main(string[] args) {
						//create a new object of type DogShelter
            DogShelter shelter = new DogShelter();
						//for each dog in the DogShelter object
            foreach(Dog dog in shelter) {//error because the DogShelter class does't implement the IEnumerable interface yet
                //if the dog is not naughty (good boy)
								if (!dog.IsNaughtyDog) {
										//give this dog 2 treats
                    dog.GiveTreat(2);
                } else {
										//also give treats :) but only 1
                    dog.GiveTreat(1);
                }
            }
        }
    }
}

We will Immediately see an error , This error is saying that our class lacks the ability to be Enumerated through

To fix this we need to implement the interface IEnumerbale<T> where T is going to be the type of objects that we will enumerate through which in our case is Dog

first, since this interface is concerned with the generic collections, we need to import the generic collections namespace

after we implement the interface IEnumerable<Dog> our class should look like this

class DogShelter: IEnumerable<Dog> {// error because this class doesn't provide it's implementation of the methods from the IEnumerable interface

      //list of type List<Dog>
        public List<Dog> dogs;
				//this constructor will initialize the dogs list with some values
        public DogShelter() {
            //initialize the dogs list using the collection-initializer
						dogs = new List<Dog>() {
                new Dog("Casper",false),
                new Dog("Sif",true),
                new Dog("Oreo",false),
                new Dog("Pixel",false),
            };
        }

    }

Now the error inside the for each loop is gone, but another error has appeared on the IEnumerable<Dog>

It is complaining because we did not implement the two methods that are inside the IEnumerable Interface, which are

  1. IEnumerable<Dog>.GetEnumerator() which is the method we need to implement to make our class Enumerable.
  2. IEnumerable.GetEnumerator() which is the non-generic version of the first method

Now the reason we need to implement the second method (non-generic version) is to ensure backward compatibility with the non-generic collections just in case because the generic collections came after the non-generic collections

Let’s hit show potential fixes

and then select Implement Interface

These will the two methods we mentioned above in our class

The class should look like this afterward

class DogShelter  : IEnumerable<Dog> {

        //list of type List<Dog>
        public List<Dog> dogs;
				//this constructor will initialize the dogs list with some values
        public DogShelter() {
            //initialize the dogs list using the collection-initializer
						dogs = new List<Dog>() {
                new Dog("Casper",false),
                new Dog("Sif",true),
                new Dog("Oreo",false),
                new Dog("Pixel",false),
            };
        }

				//this method will get generated for us 
				//we will use this method to provide implementation to the GetEnumerator() method of the IEnumerator interface
        public IEnumerator<Dog> GetEnumerator() {
            throw new NotImplementedException();
        }
	
				//this method will get generated for us
				//since in this example we won't be passing our class to a non-generic method we don't need to provide an implementation for it at this point
        IEnumerator IEnumerable.GetEnumerator() {
            throw new NotImplementedException();
        }
    }

Now since generic collections implement the IEnumerable Interface, then they also have their own implementation of the GetEnumerator() method, Which means in our case since the DogShelter uses a List<Dog> as a collection then we can use the GetEnumerator() of that list as a workaround

Our DogShelter class should then look like this

class DogShelter : IEnumerable<Dog> {

       //list of type List<Dog>
        public List<Dog> dogs;
				//this constructor will initialize the dogs list with some values
        public DogShelter() {
            //initialize the dogs list using the collection-initializer
						dogs = new List<Dog>() {
                new Dog("Casper",false),
                new Dog("Sif",true),
                new Dog("Oreo",false),
                new Dog("Pixel",false),
            };
        }

			 //this method will get generated for us 
			 //we will use this method to provide implementation to the GetEnumerator() method of the IEnumerator interface
       public IEnumerator<Dog> GetEnumerator() {
						//since our list of dogs is a generic collection that already implements its own IEnumerable interface
						//we will return it
            return dogs.GetEnumerator();
        }

				//this method will get generated for us
				//since in this example we won't be passing our class to a non-generic method we don't need to provide an implementation for it at this point
        IEnumerator IEnumerable.GetEnumerator() {
            throw new NotImplementedException();
        }
    }

Complete Code


using System;
using System.Collections.Generic;

namespace IEnumerableandIEnumerator {

    class Program {

        static void Main(string[] args) {

           //create a new object of type DogShelter
            DogShelter shelter = new DogShelter();
						//for each dog in the DogShelter object
            foreach(Dog dog in shelter) {//error because the DogShelter class does't implement the IEnumerable interface yet
                //if the dog is not naughty (good boy)
								if (!dog.IsNaughtyDog) {
										//give this dog 2 treats
                    dog.GiveTreat(2);
                } else {
										//also give treats :) but only 1
                    dog.GiveTreat(1);
                }
            }
        }
    }

//a class named Dog which we will use in another class called DogShelter which will contain a collection of this class
class Dog {
				//the name of the dog
        public string Name { get; set; }
        //is this a naughty dog
				public bool IsNaughtyDog { get; set; }
				//simple constructor 
        public Dog(string name,bool isNaughtyDog) {
            this.Name = name;
            this.IsNaughtyDog = isNaughtyDog;

        }
				//this method will print how many treats the dog received 
        public void GiveTreat(int numberofTreats) {
						//print a message containing the number of treats and the name of the dog
            Console.WriteLine("Dog: {0} said wuoff {1} times!.", Name, numberofTreats);
            
        }
    }

class DogShelter : IEnumerable<Dog> {

       //list of type List<Dog>
        public List<Dog> dogs;
				//this constructor will initialize the dogs list with some values
        public DogShelter() {
            //initialize the dogs list using the collection-initializer
						dogs = new List<Dog>() {
                new Dog("Casper",false),
                new Dog("Sif",true),
                new Dog("Oreo",false),
                new Dog("Pixel",false),
            };
        }

			 //this method will get generated for us 
			 //we will use this method to provide implementation to the GetEnumerator() method of the IEnumerator interface
       public IEnumerator<Dog> GetEnumerator() {
						//since our list of dogs is a generic collection that already implements its own IEnumerable interface
						//we will return it
            return dogs.GetEnumerator();
        }

				//this method will get generated for us
				//since in this example we won't be passing our class to a non-generic method we don't need to provide an implementation for it at this point
        IEnumerator IEnumerable.GetEnumerator() {
            throw new NotImplementedException();
        }
    }
}
Lost in coding? Discover our Learning Paths!
Lost in coding? Discover our Learning Paths!
Enter your email and we will send you the PDF guide:
Enter your email and we will send you the PDF guide