Published Wednesday, October 03, 2007 3:05 AM by mtaulty

LINQ? Single Step this code...

I've written probably 10 - 20 different little applications that I try to use to highlight the differences between IQueryable and IEnumerable previously and, just recently, I've written another one.

I think this is a really interesting piece of code. Take it, compile it (in VS 2008) and press F10. Now, continue to press F11 until the program stops - repeat until satisfied with what's going on. I find the iterators aspect of it all quite entertaining as the debugger appears to step into functions in the wrong order.

using System;
using System.Collections.Generic;
using System.Collections;

class Program
{
  static void Main(string[] args)
  {
    Console.ForegroundColor = ConsoleColor.Yellow;
    Console.WriteLine("Enumerable...");

    #region Enumerable 

    IEnumerable<int> enumerable = 
      new List<int>() { 10, 20, 30, 40, 50 };

    var query = from i in enumerable
                where i > 20
                select i * 2;

    // Enumerate to get the operators to do their work
    foreach (var result in query)
    {
    }

    #endregion

    Console.ForegroundColor = ConsoleColor.Green;
    Console.WriteLine("\nQueryable");

    #region Queryable

    System.Linq.IQueryable<int> queryable = 
      System.Linq.Queryable.AsQueryable(enumerable);

    query = from i in queryable
            where i > 20
            select i * 2;

    // Enumerator to get the operators to do their work
    foreach (var result in query)
    {
    }

    #endregion
  }
}

public static class Extensions
{
  public static IEnumerable<R> Select<R, T>(this IEnumerable<T> list,
    Func<T, R> selector)
  {
    Console.WriteLine("SELECT starting...");

    foreach (var v in list)
    {
      Console.WriteLine("\tSELECT returning item...");
      yield return (selector(v));
    }
    Console.WriteLine("SELECT finished.");
  }

  public static IEnumerable<T> Where<T>(this IEnumerable<T> list,
    Predicate<T> predicate)
  {
    Console.WriteLine("WHERE starting...");

    foreach (var v in list)
    {
      Console.WriteLine("\tWHERE returning item...");
      if (predicate(v))
      {
        yield return (v);
      }
    }
    Console.WriteLine("WHERE finished.");
  }

  public static System.Linq.IQueryable<R> Select<R, T>(this System.Linq.IQueryable<T> list,
    System.Linq.Expressions.Expression<Func<T, R>> selector)
  {
    Console.WriteLine("SELECT called with [{0}]", selector);
    Console.WriteLine("  Inner clause [{0}]", list.Expression);
    Console.WriteLine();
    return (System.Linq.Queryable.Select<T,R>(list, selector));
  }

  public static System.Linq.IQueryable<T> Where<T>(this System.Linq.IQueryable<T> list,
    System.Linq.Expressions.Expression<Func<T,bool>> predicate)
  {
    return (System.Linq.Queryable.Where<T>(list, predicate));
  }
}

# LINQの動作を確認する @ Thursday, October 04, 2007 2:22 AM

Mike Taulty's Blog : LINQ? Single Step this code...  サンプルプログラムの動作結果はこうなります。   IEnumerableとIQueryableの動作の違いが見てわかりますね...

どっとねっとふぁんBlog