Yield and generics rock!

In this post, I'll try to show you why you should not limit your use of generics to strongly typed lists, and why yield may become your favorite new keyword.
Here's an example of how you can use both in a very simple piece of code.
Imagine you want to filter out an enumeration using an arbitrary function. For obvious performance reasons, you don't want to create a temporary list and filter that. You have to construct the filtered enumeration on-the-fly as the original enumeration is enumerated.
Of course, you can do that with .NET 1.1, but if you try it, you'll see that the code will be considerably more verbose. Here's how it may be done with .NET 2.0:
 

public sealed class FilteredEnumerable<T> : IEnumerable<T>, IEnumerable {

  private IEnumerable<T> _enumerable;
  private Predicate<T> _filter;

  public FilteredEnumerable(IEnumerable<T> enumerable, Predicate<T> filter) : base() {
    _enumerable = enumerable;
    _filter = filter;
  }

  IEnumerator<T> IEnumerable<T>.GetEnumerator() {
    foreach (T item in _enumerable) {
      if (_filter == null || _filter(item)) {
        yield return item;
      }
    }
  }

  IEnumerator IEnumerable.GetEnumerator() {
    return (IEnumerator)(((IEnumerable<T>)this).GetEnumerator());
  }
}

The class is constructed from two generics of types IEnumerable<T> and Predicate<T>. A Predicate<T> is a boolean function that takes an argument of type T. That will be our filtering function. The actual code, the generic GetEnumerator function, enumerates the original enumeration, tests if the predicate returned true for this item, and yields it only in this case.
You can use this class this way:
 

string[] stringsToFilter = new string[] {"Red", "Green", "Blue", "Pink"};
Predicate<string> filter = delegate(string stringToFilter) {
  return (stringToFilter.IndexOf('e') != -1);
};
filteredStrings = new FilteredEnumerable<string>(stringsToFilter, filter);

The filteredStrings enumerable then contains all strings from stringsToFilter that contain the letter "e": red, green and blue, but not pink. Pretty slick, eh? Note the use of an anonymous function here to construct the filtering predicate. Now, you've got a generic class that filters anything by any function.

2 Comments

Comments have been disabled for this content.