Click here to Skip to main content
11,501,956 members (71,699 online)
Click here to Skip to main content

Enumerating Objects in C#

, 8 May 2007 56.7K 28
Rate this:
Please Sign up or sign in to vote.
A tutorial on enumerating objects in C#

Introduction

Like C# provides indexers to index elements within objects, C# also provides us with Enumerators to allow us enumerate through the elements within the objects. We need to use an Interface IEnumerator to enumerate through the elements of the object.

Seems like the technical jargon is undigestible? Let's understand what we wish to do through small examples. Consider the following example.

P1.cs

class Demo
{
  public static void Main ()
  {
    string []  a = new string[3] {"One" , "Two" ,"Three"};
 
    //Using the foreach loop
    foreach( string s in a)
            System.Console.WriteLine(s);
    
    // Using the Enumerator Interface
    System.Collections.IEnumerator en = a.GetEnumerator();
    while(en.MoveNext())
        System.Console.WriteLine(en.Current);
  }
}

Output

One
Two
Three
One
Two
Three

The above program compiles and runs successfully to give the desired output. The above program contains an array of three strings. We print the array using foreach loop as well as using the IEnumerator interface.

Our goal is to have objects of a class use foreach loop and IEnumerator interface exacly as shown in the above program. So let's write a program to implement such a functionality step by step. Remember! Please dont compile and run the program until I say so!

We wish to have a program such that it creates an object of a class and uses it in the foreach loop and extracts the elements of the object one by one in the following way

P2.cs

using System ;
using System.Collections ;
 
class Demo
{
  public static void Main ()
  {
    Str spp = new Str();
 
    foreach( string i in spp)
            System.Console.WriteLine(i);
 
  }
}

Ok! So in our program we have a class Str. So the program should look like this:

P2.cs

using System ;
using System.Collections ;
 
class Demo
{
  public static void Main ()
  {
    Str spp = new Str(); 
    foreach( string i in spp)
            System.Console.WriteLine(i); 
  }
}
 
class Str
{
 
}

We should be able to use object of class Str in foreach loop. The instance of our class Str in our program is spp. In the foreach loop we extract every string in the instance of class spp and print it. So it's obvious that the class should have strings as data members. Let's have class Str hold an array of strings.

P2.cs

using System ;
using System.Collections ;
 
class Demo
{
  public static void Main ()
  {
    Str spp = new Str();
 
    foreach( string i in spp)
            System.Console.WriteLine(i); 
  }
}
 
class Str
{
   string []  str_arr = new string[5] {"one" , "two" ,"three", "four", "five"};
}

OK. So we have a class Str. It contains an array of five strings. And we want to use the instance of class Str in the foreach loop and print the strings that belong to the instance. Our program is very much incomplete at this moment.

For our class Str to be used in the foreach loop we must ensure that our class implements the IEnumerable Interface. So lets have our class Str impliment the IEnumerable Interface.

P2.cs

using System ;
using System.Collections ;
 
class Demo
{
  public static void Main ()
  {
    Str spp = new Str();
 
    foreach( string i in spp)
            System.Console.WriteLine(i);
  }
}
 
class Str : IEnumerable // To impliment GetEnumerator method
{
    string []  str_arr = new string[5] {"one" , "two" ,"three", "four","five"};
}

IEnumerable interface has got one public method called GetEnumerator(). Implementing the IEnumerable Interface means implimenting the method GetEnumerator(). So let's go ahead an implement the method GetEnumerator.

P2.cs

using System ;
using System.Collections ;
 
class Demo
{
  public static void Main ()
  {
    Str spp = new Str();
 
    foreach( string i in spp)
            System.Console.WriteLine(i);
 
  }
}
 
class Str : IEnumerable // To impliment GetEnumerator method
{
   string []  str_arr = new string[5] {"one" , "two" ,"three", "four", "five"};

   public IEnumerator GetEnumerator( )
   { 
      IEnumerator r = new StrEnumerator(); 
      return r ; 
   } 
}

OK. We implimented the GetEnumerator method. It returns an object that impliments interface IEnumerator.

Now let's look at the code of the GetEnumerator Function. Inside it we are creating an object of class StrEnumerator and storing the reference in a reference variable of type IEnumerator. Next the reference is returned from the function.

OK! So we need to have a class StrEnumerator.

P2.cs

using System ;
using System.Collections ;
 
class Demo
{
  public static void Main ()
  {
    Str spp = new Str();
    foreach( string i in spp)

            System.Console.WriteLine(i);
  }
} 

class Str : IEnumerable // To impliment GetEnumerator method
{
   string []  str_arr = new string[5] {"one" , "two" ,"three", "four", "five"};
 
   public IEnumerator GetEnumerator( )
   { 
      IEnumerator r = new StrEnumerator(); 
      return r ; 
   } 
}

class StrEnumerator
{

}

Our class StrEnumerator is going to help us iterate through the elements of the class Str. So it is required that the members of our class StrEnumerator should be able to access the private members of class Str. So let's have class StrEnumerstor as a nested class.

P2.cs

using System ;
using System.Collections ;
 
class Demo
{
  public static void Main ()
  {
    Str spp = new Str();
 
    foreach( string i in spp)
            System.Console.WriteLine(i); 
  }
 
class Str : IEnumerable // To impliment GetEnumerator method
{
   string []  str_arr = new string[5] {"one" , "two" ,"three", "four", "five"};
 
   public IEnumerator GetEnumerator( )
   { 
      IEnumerator r = new StrEnumerator(); 
      return r ; 
   } 

   class StrEnumerator
   {
 
   }
}

OK! Now let's have data members for class StrEnumerator.

P2.cs

using System ;
using System.Collections ; 

class Demo
{
  public static void Main ()
  {
    Str spp = new Str();
    foreach( string i in spp)
            System.Console.WriteLine(i);
  }
}
 
class Str : IEnumerable // To impliment GetEnumerator method
{
   string []  str_arr = new string[5] {"one" , "two" ,"three", "four", "five"};

   public IEnumerator GetEnumerator( )
   { 
      IEnumerator r = new StrEnumerator(); 
      return r ; 
   } 
 
   class StrEnumerator
   {
      int index;
      Str sp;
   }
}

The integer index is required to keep a count of elements as we enumerate each element. sp is a reference of type class Str. Now let's define a constructor for class StrEnumerator.

P2.cs

using System ;
using System.Collections ;
 
class Demo
{
  public static void Main ()
  {
    Str spp = new Str();
 
    foreach( string i in spp)
            System.Console.WriteLine(i); 
  }
}
 
class Str : IEnumerable // To impliment GetEnumerator method
{
   string []  str_arr = new string[5] {"one" , "two" ,"three", "four", "five"};
 
   public IEnumerator GetEnumerator( )
   { 
      IEnumerator r = new StrEnumerator(this); 
      return r ; 
   } 
 
   class StrEnumerator
   {
      int index;
      Str sp;
      
      public StrEnumerator (Str str_obj)
      {
           index = -1 ;
           sp = str_obj ;           
      }
   }
}

Let's say that ourObject is an object of class Str. We have written the constructor in such a way that the moment GetEnumerator is executed, the constructor StrEnumerator() is passed the reference of the object ourObject. Data member sp in Class StrEnumerator now refers to the object under consideration i.e. oo.

OK. For our class Str to be used in the foreach loop we must ensure that our class StrEnumerator implements the IEnumerator Interface. Implimenting the IEnumerator Interface means Class StrEnumerator must define three methods: Current, MoveNext and Reset.

P2.cs

using System ;
using System.Collections ;
 
class Demo
{
  public static void Main ()
  {
    Str spp = new Str();
 
    foreach( string i in spp)
            System.Console.WriteLine(i);
   }
}
 
class Str : IEnumerable // To impliment GetEnumerator method
{
   string []  str_arr = new string[5] {"one" , "two" ,"three", "four", "five"};
  
   public IEnumerator GetEnumerator( )
   { 
      IEnumerator r = new StrEnumerator(this); 
      return r ; 
   } 
 
   class StrEnumerator
   {
      int index;
      Str sp;
      
      public StrEnumerator (Str str_obj)
      {
           index = -1 ;
           sp = str_obj ;           
      }
 
      public object Current
      { 
         get
         { 
             return sp.str_arr[ index ] ;  
         } 
      } 
 
      public bool MoveNext( )
      { 
         if ( index < sp.str_arr.Length - 1 )
         { 
             index++ ;
             return true ; 
         } 
         return false ; 
      } 
 
      public void Reset( )
      { 
         index = -1 ; 
      }  
   }
}

Ok! We are Done! Compile and Run the program. The program Compiles and runs successfully to give the following output.

one
two
three
four
five

Curent() is invoked to read the current value. MoveNext() is invoked to read the next value by incrementing the index count. A true is returned if the end of list is not reached. A False is returned on end of list to be returned, it returns a false. After MoveNext() returns a False, signifyiing end of list, Reset() is executed.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Chetan Kudalkar
Software Developer (Senior)
India India
I am a Software engineer with around 7+ years of experience. Most of my experience is in Storage technology.

Comments and Discussions

 
GeneralMy vote of 5 Pin
Neeraj K Sharma4-Oct-12 1:05
memberNeeraj K Sharma4-Oct-12 1:05 
BugProducing Error try compiling last peice of code.. Pin
Member 406972417-Aug-12 14:55
memberMember 406972417-Aug-12 14:55 
GeneralMy vote of 5 Pin
john_hartley11-Oct-11 15:35
memberjohn_hartley11-Oct-11 15:35 
GeneralMy vote of 1 Pin
Robert Yaeger15-Jun-10 20:57
memberRobert Yaeger15-Jun-10 20:57 
Generalcompilation error Pin
Harish Iyer20-Jun-07 4:43
memberHarish Iyer20-Jun-07 4:43 
GeneralRe: Thanks Pin
Chetan Kudalkar21-Jun-07 2:29
memberChetan Kudalkar21-Jun-07 2:29 
Generalyield keyword Pin
marlongrech8-May-07 19:16
membermarlongrech8-May-07 19:16 

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 | Terms of Use | Mobile
Web04 | 2.8.150520.1 | Last Updated 8 May 2007
Article Copyright 2007 by Chetan Kudalkar
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid