Microsoft & .NETVisual C#Eliminate Unnecessary Code and Boost Performance with C# 2.0 Iterators

Eliminate Unnecessary Code and Boost Performance with C# 2.0 Iterators

Developer.com content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

A design pattern is a solution that focuses on solving a particular problem or issue that commonly occurs. Design patterns are often associated with object-oriented programming, but they are not exclusive to it. Non-computing disciplines also have concepts similar to the design pattern, which is likely from where programmers borrowed the concept.

The existence of a design pattern does not imply that only one solution to the problem exists, nor does it mean it is the best solution in all cases. Patterns merely provide a best-practice approach to a particular problem as learned through the countless experiences of the programming community. There are often several variations of a pattern for a particular problem. It is up to each programmer to determine if and when to apply a particular pattern. Often, the programming environment in use can influence the choice of which pattern to apply. Not all programming environments and languages support all design patterns. What may be easy to create in one environment or language may be extremely difficult in another. (Find more examples of design patterns in the article titled “Implement Common Creational Design Patterns“.)

The idea behind the iterator design pattern is to expose a controlled manner to sequentially access the elements of an aggregate object without exposing its internal representation or design. Actions such as First(), Next(), CurrentItem(), and IsDone() are commonly exposed operations. Many of the System.Collection namespace classes implement the iterator pattern. Although they may use different names for the operations, they’re basically the same. They expose a GetEnumerator() method, which returns the concrete iterator for the particular class. The iterator is used to traverse the structure.

Iterator Implementation Sample Code

The following sample code demonstrates an implementation of the iterator design pattern in the 1.0 and 1.1 versions of the Microsoft .NET Framework. It implements the IEnumerable interface in an outer class, which mandates the GetEnumerator method be implemented. This allows you to use it in foreach loops:

using System;using System.Collections;namespace CodeGuru.IteratorsSample{   class IteratorTest : IEnumerable   {      private ArrayList items = new ArrayList();      public int Count      {         get { return items.Count; }      }      public object this[int index]      {         get { return items[index]; }         set { items.Insert(index, value); }      }      public IEnumerator GetEnumerator()      {         return new IteratorSampleEnumerator(this);      }      private class IteratorSampleEnumerator : IEnumerator      {         IteratorTest aggregate = null;         int index = -1;         public IteratorSampleEnumerator(IteratorTest aggregate)         {            this.aggregate = aggregate;         }         public virtual object Current         {            get { return this.aggregate[index]; }         }         public virtual bool MoveNext()         {            index++;            if (index >= this.aggregate.Count)            {               return false;            }            else            {               return true;            }         }         public virtual void Reset()         {            index = -1;         }      }   }   class Program   {      static void Main(string[] args)      {         // Create an iterator and add sample data         IteratorTest tests = new IteratorTest();         tests[0] = "Test 1";         tests[1] = "Test 2";         tests[2] = "Test 3";         tests[3] = "Test 4";         tests[4] = "Test 5";         foreach (object test in tests)         {            Console.WriteLine(test);         }         // Wait for the user so we can see output         Console.ReadLine();      }   }}

The sample output from the application will look something like this:

Test 1Test 2Test 3Test 4Test 5

To return an IEnumerator instance, you need another class that has intimate knowledge of your class and can iterate through the internal aggregate implementation.

C# 2.0 Iterators

As you may have noticed in the example, the iterator design pattern isn’t overly difficult to implement. However, those of you who have read many of my prior articles know that I’m all about eliminating unnecessary code and performance overhead. Hence, the prior implementation has both unnecessary code and performance overhead. If the implementation involves value types, boxing and unboxing get involved, which leads to the performance overhead. The unnecessary code results from the iterator needing in-depth knowledge of the aggregate class. With C# 2.0, you can rely on generics and the compiler to help reduce the amount of code and performance impact. A new yield statement appears only inside an iterator block. Each call to GetEnumerator will yield the next value in the collection, and all of the state management is handled.

C# 2.0 Iterator Implementation Sample Code

The following sample code removes the nested class from the previous example. It replaced the entire GetEnumerator method to use the yield statement. Additionally, it includes the use of generics so you can apply the example to any type:

using System;using System.Collections;using System.Collections.Generic;namespace CodeGuru.IteratorsSample{   class IteratorTest2<T> : IEnumerable   {      private ArrayList items = new ArrayList();      public int Count      {         get { return items.Count; }      }      public T this[int index]      {         get { return (T)items[index]; }         set { items.Insert(index, value); }      }      public IEnumerator GetEnumerator()      {         foreach (T item in this.items)         {            yield return item;         }      }   }   class Program   {      static void Main(string[] args)      {         // Create an iterator and add sample data         IteratorTest2<string> tests = new IteratorTest2<string>();         tests[0] = "Test 1";         tests[1] = "Test 2";         tests[2] = "Test 3";         tests[3] = "Test 4";         tests[4] = "Test 5";         foreach (string test in tests)         {            Console.WriteLine(test);         }         // Wait for the user so we can see output         Console.ReadLine();      }   }}

The sample output from the application will look just like it did before:

Test 1Test 2Test 3Test 4Test 5

There is less code involved in the overall solution and the performance is improved.

Future Columns

The topic of the next column has yet to be determined. If you have something in particular that you would like to see explained, please e-mail me at mstrawmyer@crowechizek.com.

About the Author

Mark Strawmyer (MCSD, MCSE, MCDBA) is a senior architect of .NET applications for large and mid-sized organizations. Mark is a technology leader with Crowe Chizek in Indianapolis, Indiana. He specializes in architecture, design, and development of Microsoft-based solutions. Mark was honored to be named a Microsoft MVP for application development with C# for the second year in a row. You can reach Mark at mstrawmyer@crowechizek.com.

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Latest Posts

Related Stories