Click here to Skip to main content
Click here to Skip to main content

Foreach On IEnumerable

By , 6 Aug 2013
Rate this:
Please Sign up or sign in to vote.

Introduction

I was working with my team on a regular working day. I was using foreach loop and one of my co-developers asked me if I used the IEnumerable collection variable in a foreach loop constructor. I was aware that foreach loop can apply on the IEnumerable but I was not aware why.

So I searched MSDN for IEnumerable and I got my answer.

I would like to share this with you.

Background

Let me make a few statements as my background for the concept.

  • The IEnumerable<T> interface is a generic interface that provides an abstraction for looping over elements. In addition to providing foreach support, it allows you to use extension methods in the System.Linq namespace.
  • foreach loop is used on a collection that implements the IEnumerable interface.
  • foreach loop returns each element of a collection in the order it is called in the enumeration. 
  • foreach provides in order element access from a collection; it does not accept index and provides access to elements, so eliminates errors caused by incorrect index handling. 
  • IEnumerable is an interface enforcing a rule that we need to implement the GetEnumerator method.
  • GetEnumerator method returns an IEnumerator interface.

Following is the signature for the GetEnumerator method.

public IEnumerator GetEnumerator(void) 

Now we have to implement the IEnumerator interface with the IEnumerable interface in order to accept a return value from the GetEnumerator method.

The IEnumerator interface enforces rules that we need to implement as follows:

  • MoveNext method [public bool MoveNext(void)]
    • Increment collection counter by one
    • If end of collection has been reached, it will return false else return true
  • Reset method [pubic void Reset(void)]
    • Resets the collection index to its initial value of -1
  • Current method [public object Current(void)]
    • Return the current index object from collection

Using the Code

  • Start Microsoft Visual Studio
  • Open File->New->Project->Console Application
  • Give some nice name to console application
  • Open Project->AddClass
  • Give name Employee to it
    public class Employee
    {
        private int employee_Id;
        private string employee_Name;
    
        public Employee(int employee_Id, string employee_Name)
        {
            this.employee_Id = employee_Id;
            this.employee_Name = employee_Name;
        }
    
        public int Employee_Id { get { 
                                        return employee_Id; 
                                     }
                                 set {
                                       employee_Id=value; 
                                     } 
                                }
    
        public string Employee_Name {
                                        get {
                                              return employee_Name; 
                                            } 
                                        set { 
                                             employee_Name=value; 
                                            } 
                                    }
    }
  • Employee class is a single unit type in the foreach loop.
  • We have exposed two properties Employee_Id and Employee_Name.
  • Now let’s start creating our collection that would be applied on the Foreach loop.
  • Let’s start following statements that we had stated in the background.
  • Create class Employees and implement the IEnumerable and IEnumerator interfaces.
  • We will also create an Employee class array collection and initialize in the constructor by adding an Employee object into the collection of the Employee array.
  • public class Employees : IEnumerable,IEnumerator
    {
        private Employee[] employeeList;
        private int position = -1;
    
        public Employees()
        {
            employeeList = new Employee[4]{
                        new Employee(1,"Amey"),
                        new Employee(2,"Pushkar"),
                        new Employee(3,"Raju"),
                        new Employee(5,"Vijay")
            };
        }
    
        public object Current
        {
            get
            {
                try
                {
                    return employeeList[position];
                }
                catch (IndexOutOfRangeException)
                {
                    throw new InvalidOperationException();
                }
            }
        }
    
        public bool MoveNext()
        {
            position++;
            return (position < employeeList.Length);
        }
    
        public void Reset()
        {
            position = 0;
        }
    
        public IEnumerator GetEnumerator()
        {
            return (IEnumerator)this;
        }
    } 
  • Let’s move to our Program class that contains the Main method.
  • Let’s use the foreach loop on the Employees class that implements the interfaces IEnumerable and IEnumerator. The Employees class contains an array collection of the Employee class. 
  • Add the following code in the Main method.
  • static void Main(string[] args)
    {
        var employees = new Employees();
        foreach (Employee employee in employees)
        {
           Console.WriteLine("Employee Id:- "+employee.Employee_Id.ToString()
                              +"\t\t"
                              +"Employee Name:- "+employee.Employee_Name);
        }
    
        Console.ReadLine();
    }
  • Run the project.

You will observe the following output:

Employee Id: - 1     Employee Name: - Amey
Employee Id: - 2     Employee Name: - Pushkar
Employee Id: - 3     Employee Name: - Raju 
Employee Id: - 5     Employee Name: - Vijay  

Code optimization

  1. Yield keyword in C#.
  2. In C#, it is not strictly necessary for a collection class to implement IEnumerable and IEnumerator in order to be compatible with foreach.

    As long as the class has the required GetEnumerator, MoveNext, Reset, and Current members, it will work with foreach.

    Or we can say that: 

    As long as the class has the required GetEnumerator() function that returns an instance that implements either an IEnumerator or IEnumerator<T> interface that enforces to use members MoveNext, Reset, and Current.

    When you use the yield keyword in a statement, you indicate that the method, operator, or get accessor in which it appears is an iterator, i.e., Yield keyword appears in an iterator block.

    When a yield return statement is reached in the iterator method, the current state of the code is retain.

    An expression that evaluates the value to enumerator [i.e., Employee class object] is returned and control moves to the caller. 

    After executing the caller block, control again moves back to the iterator method and restarts from the retain state.

    Based on the above statement, we can optimize our Employees class as below: 

    public class Employees : IEnumerable
    {
        private Employee[] employeeList;
        private int position = -1;
        public Employees()
        {
            employeeList = new Employee[4]{
                        new Employee(1,"Amey"),
                        new Employee(2,"Pushkar"),
                        new Employee(3,"Raju"),
                        new Employee(5,"Vijay")
            };
        }
    
    
        public IEnumerator GetEnumerator()
        {
            foreach(Employee employee in employeeList)
              yield return employee; 
        }
    }
  3. Foreach is not type safe.
  4. As our foreach statement in main method can be written as:

    Foreach(int employee… or Foreach (string employee ) 

    So it is not type safe, right? To make it type safe, let’s declare it as var which gets assigned its type during runtime.

    So our main function looks like below:

    static void Main(string[] args)
    {
        Employees employees = new Employees();
        foreach (var employee in employees)
        {
            Console.WriteLine("Employee Id:- " + 
            (employee as Employee).Employee_Id.ToString()
                               + "\t\t"
                               + "Employee Name:- " + 
                               (employee as Employee).Employee_Name);
        }
        Console.ReadLine();
    } 

Notes

  1. The foreach construct comes from C# 1.0, before generics existed. It worked with untyped collections such as ArrayList or IEnumerable. Therefore, the IEnumerator.Current property that gets assigned to the loop variable would usually be of type object.
  2. public object Current
    {
        get
        {
            try
            {
                return (Employee)employeeList[position];
            }
            catch (IndexOutOfRangeException)
            {
                throw new InvalidOperationException();
            }
        }
    }
  3. Iterator Pattern falls into the behavioral category. Iterator pattern helps developers to expose a collection element access in a controlled manner. An iterator allows sequential access of elements without exposing the inside code. It protects a collection from errors like error caused by incorrect index handling. When a developer uses a foreach loop he is using the Iterator Pattern knowing or unknowingly.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Amey K Bhatkar
Web Developer Lionbridge
India India
Amey K Bhatkar, a “Microsoft .Net” Web Developer.
I am programmer by will and profession.
I have completed my MCA in 2011 and join software industry.
Presently I am working with Lion Bridge Technologies in Mumbai - India
Follow on   Twitter   Google+

Comments and Discussions

 
GeneralMy vote of 2 PinmemberPaul K T12-Aug-13 7:53 
GeneralMy vote of 3 PinmemberJasmine250112-Aug-13 7:26 
GeneralMy vote of 3 PinprofessionalAmir Mohammad Nasrollahi28-Jul-13 19:43 
SuggestionImplementing IEnumerable and IEnumerator on the same class PinmemberJohn Brett3-Jun-13 22:41 
GeneralRe: Implementing IEnumerable and IEnumerator on the same class PinmemberDaniele Rota Nodari28-Jul-13 23:23 
GeneralMy vote of 1 PinmembertumbledDown2earth30-May-13 1:47 
GeneralRe: My vote of 1 PinprofessionalAmey K Bhatkar27-Jul-13 6:25 
QuestionI don't think your foreach statement is type-safe? PinmemberGeorge Swan27-May-13 0:38 
AnswerRe: I don't think your foreach statement is type-safe? PinprofessionalAmey K Bhatkar29-May-13 0:27 
GeneralRe: I don't think your foreach statement is type-safe? PinmemberGeorge Swan29-May-13 2:40 
SuggestionIf you use C# 2.0 or above, "yield" is a nice alternative to writing your own enumerator class PinmemberAndreas Gieriet16-Apr-13 8:39 
GeneralRe: If you use C# 2.0 or above, "yield" is a nice alternative to writing your own enumerator class PinprofessionalAmey K Bhatkar26-May-13 19:35 
GeneralRe: If you use C# 2.0 or above, "yield" is a nice alternative to writing your own enumerator class PinmemberAndreas Gieriet26-May-13 21:01 
GeneralRe: If you use C# 2.0 or above, "yield" is a nice alternative to writing your own enumerator class [modified] PinprofessionalAmey K Bhatkar27-May-13 5:05 
GeneralYour statment on IEnumerable is not fully correct... PinmemberAndreas Gieriet16-Apr-13 8:17 
GeneralRe: Your statment on IEnumerable is not fully correct... PinprofessionalAmey K Bhatkar26-May-13 19:42 
GeneralRe: Your statment on IEnumerable is not fully correct... PinprofessionalRichard Deeming7-Jun-13 5:41 
GeneralRe: Your statment on IEnumerable is not fully correct... PinmemberAndreas Gieriet9-Jun-13 16:35 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.140415.2 | Last Updated 6 Aug 2013
Article Copyright 2013 by Amey K Bhatkar
Everything else Copyright © CodeProject, 1999-2014
Terms of Use
Layout: fixed | fluid