Friday, 5 October 2007

C# yield return/break

yield is cool (you may already notice that I basically think everything's cool), the main reason is that it reminds me about Mozart Oz (which has pure logic form of programming style). There is no relationship between them, but one just made me remind the other. It's interesting to see how human's brain categorize stuff. Anyway.

yield is used to provide enumeration over objects or to signal the end of iteration. Here is a basic non-generic example from MSDN, which basically return a list of numbers from n^1 to n^m:

public static IEnumerable Power(int n, int m)
{
int counter = 0;
int result = 1;
while (counter++ < m)
{
result = result * n;
yield return result;
}
}

static void Main()
{
// Display powers of 2 up to the exponent 8:
foreach (int i in Power(2, 8))
{
Console.Write("{0} ", i);
}
}

I have to say this is not interesting at all.


However when we combine the power of yield, generics and predicates, that's where the fun is. I have copied a piece of code from Andre's blog (look at the Extended Enumerable created here): 


public delegate R Func<T, R>(T t);
public static class SequenceOperators
{
public static IEnumerable<R> Select<T, R>
(IEnumerable<T> sequence, Func<T, R> mapping)
{
foreach (T t in sequence)
yield return mapping(t);
}



public static IEnumerable<T> Where<T>
(IEnumerable<T> sequence, Predicate<T> filter)
{
foreach (T t in sequence)
if (filter(t))
yield return t;
}
}

So, how exciting! The Select method takes an IEnumerable<T> and a function which has input param type T  (you know it's not really "T") and return type R (not Civic type R). By passing every t in T into the function, an enumeration of R objects were returned. The Where method takes an IEnumerable<T> and a predicate, and return enumeration of T objects of t in T that match the criteria.


It's so flexible and powerful. :)

No comments:

Post a Comment