Quantcast
Channel: C# Help » Looping
Viewing all articles
Browse latest Browse all 4

Building Your Own C# Enumerator To Use With The foreach Construct

$
0
0


We are going to use "foreach" to iterate through our collection of fruit objects.

Lets assume that we have a class called Fruitwhich contains the fields; string name ,int num and bool ripe. We builda class called Fruits which represents a collection of fruit objects.

public class Fruits
{
//we don?t have to specify private as this is the default modifier
//it?s just included to highlight the fact that this is private to
//the Fruits collection.

private Fruit[] fruitArray;

//Create a basket of fruit

public Fruits()
{
fruitArray = new Fruit[3];
fruitArray[0] = new Fruit("Banana",false,3);
fruitArray[1] = new Fruit("Apples",true,5);
fruitArray[2] = new Fruit("Oranges",true,3);
}
}

In order to obtain each Fruit from the Fruitscollection it would be convenient if the object user could iterate overthe Fruits type using the foreach construct. It would be reasonable tocode:

public class FruitBar
{
public static void Main()
{
Fruits fruitbasket = new Fruits();
//Show only the ripe fruit
foreach (Fruit f in fruitbasket)
{
if (f.ripe == true)
{
Console.WriteLine("Name : {0}",f.name);
Console.WriteLine("Amount : {0}",f.num);
}
{
}
}

Unfortunately attempting to execute this code results in the compiler complaining that it cannot find GetEnumerator.

To use the foreach syntax your class mustsupport the IEnumerable interface found in the System.Collectionsnamespace. IEnumerable defines only one method, public IEnumeratorGetEnumerator(), notice that this method returns another interfaceIEnumerator also found in System.Collections namespace.

IEnumerator supports a simple iteration over a collection. It publishes two methods and a property:

bool MoveNext():
Advances the enumerator tothe next element in the collection. Returns true if successfullyadvanced to the next element in the collection and false if the movewould take it beyond the last element.

void Reset():
Sets the enumerator to the initial position, which is before the first element in the collection (-1)

object Current {get;}:
Gets the current element in the collection. Throws Exception Type InvalidOperationException.

To successfully implement an enumerator wemust keep in mind the following protocol. After an enumerator iscreated or after a Reset, MoveNext must be called to advance theenumerator to the first element of the collection before reading thevalue of Current. Current throws an exception if the last call toMoveNext returns false. Current does not move the position of theenumerator.

This is by no means a thorough discussion on implementing enumeration, more an introduction to using enumerators with foreach.

Here is an example of the changes required to implement an enumerator for use with the foreach construct.

namespace MyFruitBasket
{
public class Fruit
{
//this is a bad way to declare fields in a class
//but this is just an example
public string name;
public bool ripe;
public int num;

public Fruit(string nme, bool rp, int n)
{
name = nme;
ripe = rp;
num = n;
}
}

The Fruits collection implements the IEnumerable and IEnumerator interfaces.

public class Fruits :IEnumerable,IEnumerator
{
Fruit[] fruitArray;
//current position in array set to initial position
int position = -1;
//Create a basket of fruit
public Fruits()
{
fruitArray = new Fruit[3];
fruitArray[0] = new Fruit("Banana",false,3);
fruitArray[1] = new Fruit("Apples",true,5);
fruitArray[2] = new Fruit("Oranges",true,3);
}

//Implement IEnumerable

public IEnumerator GetEnumerator()
{
return (IEnumerator)this;
}

//Implement IEnumerator
public bool MoveNext()
{
position++;
if (position < fruitArray.Length)
{
return true;
}
else
{
return false;
}
}
public void Reset()
{
position = -1;
}
public object Current
{
get{return fruitArray[position];}
}
}

class FruitBar
{
static void Main(string[] args)
{
Fruits fruitbasket = new Fruits();
//Present only the ripe fruit
foreach (Fruit f in fruitbasket)
{
if (f.ripe == true)
Console.WriteLine("Name : {0}",f.name);
Console.WriteLine("Amount : {0}",f.num);
}
string x = Console.ReadLine();
}
}
}

I hope this has been of some help.


Viewing all articles
Browse latest Browse all 4

Trending Articles