LINQ Walk[source]

    <title>LINQ Walk</title>
    <description>Implementation of a walk() extension method for LINQ</description>
    <category>Legacy blog posts</category>
<glacius:macro name="legacy blargh banner">
  So, we all know that
  <a href="">LINQ</a>
  is rad. Not in that silly faux-SQL syntax, but in the declarative, fluent syntax.
  But the sad part is that there is no <code>walk</code> extension method. Walk is a 
  functional programming staple that iterates over a collection of stuff and applies a 
  callback to each item.
  You might be thinking, "but there is a <code>ForEach()</code> extension method on 
  <code>List</code>!". And you would be wrong, because there is a subtle, yet important 
  difference between <code>IEnumerable</code> and <code>IList</code>.
  <code>IEnumerable</code> is late-binding. That means you can do whatever you want to 
  it, but execution is deferred until you actually enumerate the enumeration, i.e. using a 
  <code>foreach</code> construct. In a list, there is no deferred execution. This deferred 
  execution is accomplished through the magic of closures and expression trees.
<p>In the meantime, here is a fluent implementation of <code>walk</code>:</p>
<glacius:code lang="csharp"><![CDATA[public static class LinqExtensions {
	public static IEnumerable<T> Walk<T>(this IEnumerable<T> source, Action<T> action) {
		foreach (var t in source) {
			yield return t;
<p>You can prove that this is in fact using deferred execution with a simple test:</p>
<glacius:code lang="csharp"><![CDATA[class Program {
	class Foo {
		public int Bar { get; set; }
		public override string ToString() {
			return string.Format("Foo(Bar={0})", Bar);
	static void Main() {
		IEnumerable<Foo> foos = new[] { new Foo { Bar = 2 }, new Foo { Bar = 1 }, new Foo { Bar = 3 } };
<p>The output looks like this:</p>
<p class="text-center">
  <img glacius:src="linqwalk1.png" alt="LINQ walk output" />
  Notice that nothing got printed the first time through, using the <code>Walk()</code> extension 
  method. There's your deferred execution. That means our extension method did not enumerate the 
  enumeration, so it's safe and efficient to use walk in a normal linq expression where you are 
  depending on deferred execution, like this:
<glacius:code lang="csharp"><![CDATA[
IEnumerable<Foo> foos = new[] { new Foo { Bar = 2 }, new Foo { Bar = 1 }, new Foo { Bar = 3 } };
Console.WriteLine("Doing more stuff:");
var listOStuff = foos
	.Where(foo => foo.Bar >= 2)
	.Walk(foo => foo.Bar += 10)
	.Select(foo => new Baz { Foofy = foo })
	.Walk(baz => baz.Foofy.Bar--)
	.OrderBy(baz =>; baz.Foofy.Bar);
foreach (var stuff in listOStuff) {
<p class="text-center">
  <img glacius:src="linqwalk2.png" alt="LINQ walk output 2" />
<p>Well, maybe that's not "normal." Whatever.</p>