Recipe6.5.Creating Iterators That Accept Parameters


Recipe 6.5. Creating Iterators That Accept Parameters

Problem

You need to add a new iterator that accepts parameters to a type in order for the iterator to do special processing during the looping operation.

Solution

Add a method that is public, returns an IEnumerable, and uses the yield return statement, as shown in Example 6-3.

Example 6-3. Creating iterators that accept parameters

 public class Foo  {     private List<string> _items = new List<string>();     public void AddItem(string item)     {         _items.Add(item);     }     public IEnumerator GetEnumerator()     {         for (int index = 0; index < _items.Count; index++)         {             yield return (_items[index]);         }     }     // An iterator that accepts a starting index and an ending index to iterate over     public IEnumerable GetRange(int start, int end)     {         if (start < 0)         {             throw (new IndexOutOfRangeException                     ("the start index cannot be less than zero."));         }                  if (end < start)          {              throw (new IndexOutOfRangeException(                   "the end index cannot be less than the start parameter."));          }         if (end >= _items.Count)          {              throw (new IndexOutOfRangeException(               "the end index cannot be greater than or equal to the length of the list."));         }         for (int index = start; (index < _items.Count) && (index <= end); index++)          {             yield return (_items[index]);          }      }  } 

Discussion

Adding a default iterator to a type via the GetEnumerator method is easy and straightforward. However, this forces you to give up some flexibility. For example, using the GetEnumerator method prevents you from passing in any parameters. If you can pass in parameters, you can more easily control the way the foreach loop iterates over the items in this type.

The GetRange iterator accepts both a starting and ending index value. These values indicate the index value at which to start iterating (start) and the index value at which the iterations will cease (end). The following code shows how this iterator is used:

 public static void TestIteratorMethod() {     //Create Foo object and fill it with data.     Foo f = new Foo();     f.AddItem("item1");     f.AddItem("item2");     f.AddItem("item3");     f.AddItem("item4");     f.AddItem("item5");     f.AddItem("item6");     // Display all data in Foo object.     foreach (string s in f.GetRange(3, 4))     {         Console.WriteLine(s);     } } 

This code displays the following:

 item4 item5  

which are the string elements at the third and fourth index in the _items list in the object.

Two out-of-bounds situations can occur. The first is when the end parameter is set to a value that is past the end of the _items list. The following code shows this:

     foreach (string s in f.GetRange(0, 50))      {          Console.WriteLine(s);     } 

This foreach loop will display all items in the _items list. This is because you have set up the for loop in the GeTRange iterator method to handle this situation. The for loop's conditional expression is shown here:

 for (int index = start; (index < _items.Count) && (index <= end); index++) 

The for loop will stop looping either when the index loop counter is greater than the end parameter or when it goes past the end of the _items list. Another out-of-bounds situation is when the start parameter is less than the initial index in the _items list, which is zero. The following code starts iterating at a negative start index:

     foreach (string s in f.GetRange(-3, 5))      {          Console.WriteLine(s);      } 

This causes an IndexOutOfRangeException to be thrown.

See Also

See the "Iterators," "IEnumerator Interface," and "IEnumerable Interface" topics in the MSDN documentation.



C# Cookbook
Secure Programming Cookbook for C and C++: Recipes for Cryptography, Authentication, Input Validation & More
ISBN: 0596003943
EAN: 2147483647
Year: 2004
Pages: 424

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net