Friday, December 28, 2007

Foreach in C# uses ducktype

This came to me as little surprise. May be for others too.. including my manager with whom I had discussion about this once.

So far I was under the impression that for any class to be used inside foreach, it must implement IEnumrable interface. I remember myself asking this question in interview to many guys and even answered same question in the interview when I was on other side of the interview table.

Today I am going to proove that its not true anymore.... (what??????)

Well, all you need for your class to be used inside foreach is
  • have GetEnumrator method with no input params and return type object which has two method MoveNext (returns bool) and property Current with getter (returns object)
Still not want to believe me? well here is the code snippet
using System;

namespace ForEachDemo
{
public class Program
{
private static void Main(string[] args)
{
// the following complies just fine:

Person[] peopleArray = new Person[3]
{
new Person("John", "Smith"),
new Person("Jim", "Johnson"),
new Person("Sue", "Rabon"),
};

People peopleList = new People(peopleArray);
Console.WriteLine("This program demostrate usage of foreach without implementing IEnumerable interface.");
foreach (Person p in peopleList)
Console.WriteLine(p.firstName + " " + p.lastName);

Console.WriteLine("Press return key to exit...");
Console.ReadLine();
}
}

public class People
{
private Person[] _people;

public People(Person[] persons)
{
_people = persons;
}

public PeopleEnum GetEnumerator()
{
return new PeopleEnum(_people);
}
}

public class PeopleEnum
{
private Person[] _people;

// Enumerators are positioned before the first element
// until the first MoveNext() call.
private int position = -1;

public PeopleEnum(Person[] list)
{
_people = list;
}

public bool MoveNext()
{
position++;
return (position < _people.Length);
}

public void Reset()
{
position = -1;
}

public object Current
{
get
{
try
{
return _people[position];
}
catch (IndexOutOfRangeException)
{
throw new InvalidOperationException();
}
}
}
}

public class Person
{
public Person(string fName, string lName)
{
firstName = fName;
lastName = lName;
}

public string firstName;
public string lastName;
}
}

just copy paste this in empty console app and look at the result. You will be more than surprised to see what is happening....

Obvious question you might want to ask here is what the F**k is going on here. The answer to this is foreach in C# (may be even VB.NET, I didn't tried my self) uses ducktype.

Develop smartly:)

No comments: