Hi and welcome to my blog. Im Tasos, a software engineer working in the UK. This is where i share some of my findings related with SQL, c#, asp.net and javascript with you. I hope you find something helpful and Im looking forward to your feedback!

Recent Comments

Popular Posts

Recent Posts

Archives

Post Categories

Blog Stats

  • Posts: 14
  • Comments: 36
  • Trackbacks: 16
  • Articles: 1

Yield return and Iterators use case: looping through the days between a date span

Thursday, November 15, 2007 11:54 PM, Filed Under ASP.Net C#

I recently found myself in the situation where I had to loop through all the days from a StartDate to an EndDate.

Sure easy, all you need to do is something like this:

DateTime startDate = DateTime.Now;
DateTime endDate = DateTime.Now.AddDays(3);

DateTime curDate = startDate;
while (curDate <= endDate)
{
    //Do Something with curDate ...

    curDate = curDate.AddDays(1);
}

Does the job, but it is not very intuitive in my opinion. It is not that easy to read.
Wouldn't it be so much nicer if we could do something like this:

DayIterator dayIterator = new DayIterator(startDate, endDate);
foreach (DateTime dt in dayIterator)
{
     //Do Something with dt... 
}
 

I think the second version really shows the intent of what we are trying to do and is much more easy to follow and maintain.

So how do we go about implementing the DayIterator then? As you will see for yourself it really is simple code that makes use of the yield return statement for Iterators.

Here is the implementation of the DayIterator:

    public class DayIterator : IEnumerable<DateTime>
    {

        private DateTime _StartDate;
        private DateTime _EndDate;

        public DayIterator(DateTime startDate, DateTime endDate)
        {
            _StartDate = startDate;
            _EndDate = endDate;
        }

        public IEnumerator<DateTime> GetEnumerator()
        {
            DateTime currentDate = _StartDate;
            while (currentDate <= _EndDate) // Note that our Iterator is inclusive of endDate behaving like 'between'
            {
                yield return currentDate; // <-- This is the key line
                currentDate = currentDate.AddDays(1);
            }
        }

        #region IEnumerable Members

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            throw Exception("Not Implemented");
        }

        #endregion
    }
 

Thats all it takes! Now we have our custom DayIterator class. Now when we do foreach (DateTime dt in dayIterator) what foreach does is it calls GetEnumerator to start the loop. The yield return statement within GetEnumerator returns an instance of a DateTime class so the outer foreach loop starts looping using this as the first element. Each time our code reaches the foreach statement it calls GetEnumerator again resuming from the last yield return statement. When our GetEnumerator function finishes then the outer foreach loop stops looping. So in this example the GetEnumerator will finish when the condition
while (currentDate <= _EndDate) is not true anymore and therefore the foreach loop will terminate.

We can also use yield return break within the GetEnumerator implementation if we want to terminate the foreach looping.

So I guess some of you may be wondering What's with the two GetEnumerator functions instead of just one? Well In this example we want to loop through a collection of DateTime objects for this reason we inherited the DayIterator class from IEnumerable<DateTime>. This requires us to implement both the IEnumerable<DateTime> GetEnumerator() function and the IEnumerbale GetEnumerator (the latter returns only objects and we need not implement)

Ok, this is all good but does it really work?! Well, lets put it to the test with the following little sample code:


DateTime
startDate = DateTime.Now; DateTime endDate = DateTime.Now.AddDays(5); Console.WriteLine("StartDate: {0:dd MMM yyyy}", startDate); Console.WriteLine("EndDate: {0: dd MMM yyyy}", endDate); DayIterator dayIterator = new DayIterator(startDate, endDate); foreach (DateTime dt in dayIterator) { Console.WriteLine("In foreach: {0:dd MMM yyyy} ", dt); }


This is what we get:

image

 

Now the DayIterator Class can be easily expanded to include functions such as IsCurrentDayInSameMonthAsPrevious and the resulting code again looks even more elegant in a scenario where while we are looping through the days, we want to do something on when the month changes from one day to the next for example. It is quite straightforward to implement but as an excercise I will leave it up to you to implement :)

So if you find yourself looping in a for or a while loop, take another careful look at your code, you may be able to use an Iterator and express your code intent in a more clear and concise fashion. Of course this does not mean that we take it to the other extreme abandoning all loops for Iterators!

Question:
Can I implement the IEnumerbale GetEnumerator with the same logic as IEnumerable<DateTime> GetEnumerator() but without copying down the same code in two places, how?


Further Reading:
http://www.yoda.arachsys.com/csharp/csharp2/iterators.html
http://codebetter.com/blogs/david.hayden/archive/2006/10/05/C_2300_-2.0-Iterators-and-Yield-Keyword-_2D00_-Custom-Collection-Enumerators.aspx

Share this post!
digg it
Kick it on DotNetKicks.com

Comments

# Yield return and Itirators use case: another way to loop days, Posted by DotNetKicks.com on 11/16/2007 1:12 AM

You've been kicked (a good thing) - Trackback from DotNetKicks.com

# Soma in urine., Posted by Soma. on 7/13/2008 2:54 AM

Soma.

# Danger of ephedrine., Posted by Ephedrine liquid gels. on 7/15/2008 1:27 AM

Ephedrine. Ephedrine liquid gels. Ephedrine and pregnancy. Difference between pseudoephedrine ephedrine.

# Xanax no prescription., Posted by Xanax. on 7/28/2008 9:59 AM

Xanax xr crushed. Buy 180 xanax. Buy cheap generic xanax. Xanax. Generic xanax 2 mg no prescription. Xanax lawsuits.

# Zoosex., Posted by Zoosex. on 8/9/2008 5:07 PM

Zoosex blog. Animal sex free animalsex zoosex. Free pics of zoosex. Zoosex.

# Phentermine., Posted by Phentermine mg. on 8/20/2008 1:23 AM

Phentermine online. Phentermine 37 5mg. Phentermine diet pills. Order phentermine. Cheapest phentermine.

Comments

Title: *
Name: *
Email: (never displayed)
Website:
Comment: *  
Please add 5 and 8 and type the answer here: