Wednesday, February 11, 2009

for-each-ing

People mypeople = new People();
foreach (Person indivudual in mypeople)
{
Console.WriteLine(indivudual);
}
To write a foreach loop for your collection class you need to implement IEnumerable and IEnumerator. Here’s a simple way to do it.

class Person
{
private string _Name;

public Person(string name)
{
_Name = name;
}
public override string ToString()
{
return _Name;
}
}
class People:IEnumerable
{
List<Person> people = new List<Person>();

public People()
{
people.Add(new Person("A"));
people.Add(new Person("B"));
people.Add(new Person("C"));
people.Add(new Person("D"));
}

//IEnumerable<Person> Members
public IEnumerator GetEnumerator()
{
return people.GetEnumerator();
}
}
Here instead of creating a enumerator, I am simply using the List class’s enumerator. I believe that is how you will use in most cases.

Now, you will also find IEnumerable<T> and IEnumerator<T>, they have something to do with LINQ, will post more on that later. MSDN says if you implement IEnumerable<T> then you should also implement the non-generic version of IEnumrator.

There is also something else called as iterators - if you need to return only a fragment of your collection. Heres how :

public IEnumerable<Person> ListAll()
{
foreach (Person individual in people)
{
if (individual.ToString() != "B")
yield return individual;
}
}
This can be consumed by the earlier foreach loop and it prints out all individuals except B.

Note that we could also use yield in the GetEnumerator() method.1 question, why 2 interface to do get foreach going? because 1 interface makes sure your class can be enumerated and other interface ensure the enumeration state is maintained. If you have both together then how would 2 different loops (maybe on different threads) maintain different states.

No comments: