Fun with yield, generics, and foreach

We all know that you can use C#'s foreach keyword to iterate through all items in an enumeration. Suppose you have a list of mixed-types:

            object[] list = new object[] {1,2, "abc", 5f, "def" };

Trying to enumerate through the strings like this would throw an InvalidCastException:
            foreach (string s in list)
{
                Console.WriteLine(s);
}

That's because foreach iterates through every element in the enumeration, and tries to cast each to a String. It does not just iterate through the types that match string. I assume that language choice was made so that C# doesn't need an extra type-check in every for-each.

If you just wanted strings, you could filter them out like so:
            foreach (Object o in list)
{
                string s = o as string;
                if (s == null) continue;
                Console.WriteLine(s);
}

That's probably the most efficient way to do it. Just for kicks, in C# 2.0 with generics, you could also write it like:

            foreach (String s in Filter<string, object>(list))
{
                Console.WriteLine(s);
}

Where Filter takes in an enumeration (list) and returns a enumeration for the subset that matches the filter type (string). In other words, it does: {1,2, "abc", 5f, "def" } --> {"abc", "def" };  

The Filter function could be defined as:

        // Yield set of TOut that are in the input enumeration
        static IEnumerable<TOut> Filter<TOut, TIn>(IEnumerable<TIn> list)
            where TOut : TIn // need constraint to cast TIn --> TOut
        {
            foreach (TIn o in list)
{
                if (o is TOut) yield return (TOut) o;
}
}
Note that it requires a generic constraints (the "where" keyword) in order to be able to cast TIn to TOut.

Other uses:
You can have more interesting enumeration functions too:

        static IEnumerable<int> Range(int start, int end)
{
            for (int i = start; i < end; i++) yield return i;
}

And the use that like:

        foreach (int i in Range(5, 8)) { Console.WriteLine(i); }

Or have an enumeration do a more complex calculation like compute the fibonacci series:

         // Compute fibonacci series up to Max (> 1).
        static IEnumerable<int> Fib(int max)
        {
            int a = 0;            
            int b = 1;
            yield return 1;            

            for (int i = 0; i < max - 1; i++)
            {
                int c = a +b;
                yield return c;

                a = b;
                b = c;
            }
        }

And then use it like so:

        foreach (int i in Fib(10)) { Console.WriteLine(i); }

Hey, this looks like Linq ... :
This is the type of thing that Linq does, but in a much more useful, less contrived way (see Rick's example around select). If you like this, you 're going to love Linq.