| « A quick'n easy Google web part in SharePoint Services | Dynamic proxies over delegate types » |
Filtered enumerations
In Yield and generics rock !, Bertrand Leroy exposed a very elegant way to filter an generic enumeration using the yield keyword.
He also suggested that "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". That's correct !
But .NET 1.1 is still all that is available for production purposes, so here's a possible .NET 1.1 strategy to do the same thing.
/// <summary> /// Generic representation of a predicate /// </summary> public delegate bool Predicate(object o); /// <summary> /// A class that allows to filter an enumeration. It only /// enumerates the members of the aggregated enumeration /// that conform to a given predicate /// </summary> public class FilteredEnumerable : IEnumerable,IEnumerator { readonly IEnumerator unfilteredEnum = null; readonly Predicate filter = null; /// <summary> /// Creates a new FilteredEnumerable based on an /// originally unfiltered enumeration /// and a given predicate /// </summary> /// <param name="unfilteredEnum"></param> /// <param name="filter"></param> public FilteredEnumerable(IEnumerable unfilteredEnum,
Predicate filter) { this.unfilteredEnum = unfilteredEnum.GetEnumerator(); this.filter = filter; } public IEnumerator GetEnumerator() { return this; } public void Reset() { unfilteredEnum.Reset(); } public object Current { get { return = unfilteredEnum.Current; } } public bool MoveNext() { if( filter == null ) return unfilteredEnum.MoveNext(); //Proceed to the next element of the //original enumeration //that conform to the predicate bool next = true; while( ( next = unfilteredEnum.MoveNext() ) &&
! filter(unfilteredEnum.Current) ); return next; } }
Sample code to use it :
private int CountPositiveValues(int[] tab) { FilteredEnumerable enumerable =
new FilteredEnumerable(tab,
new Predicate(IsStrictlyPostitiveInt)); int count = 0; foreach(int value in enumerable) { Console.WriteLine("Found positive value : " + value); count++; } return count; } public static bool IsStrictlyPostitiveInt(object i) { if( ! (i is int) ) throw new ArgumentException("int expected"); return ((int)i) > 0; }
Hope this helps, and sorry for those folks who may have written the same thing before, I quickly google'd for something similar but did not find anything but C# 2.0 stuff.