Fun with Anonymous Delegates & Lambda Expressions

During the course of teaching a customized offering of .NET Framework Fundamentals last week, I was showing a historical progression of delegate syntax options.  As I’ve said before, I’ve found that explaining something new to an audience in terms of something the audience already understands, is remarkably efficient.  Most of my audience already had some experience with the .NET delegate syntax on the 1.x platform, so the case study I was using to illustrate the progression of delegate syntax options was a call to Array.FindAll<T> that looked something like this (the people variable is of type Person[], where Person is a simple class not shown here):

// .NET 1.x named method + explicit construction:
//
Person[] subset = Array.FindAll(people, new Predicate<Person>(LastNameStartsWithD));
bool LastNameStartsWithD(Person p)
{
    return p.LastName.StartsWith("D");
}

...which can also be rewritten as...

// .NET 2.x named method + implicit construction:
//
Person[] subset = Array.FindAll(people, LastNameStartsWithD);
bool LastNameStartsWithD(Person p)
{
    return p.LastName.StartsWith("D");
}

...which can also be rewritten as...

// .NET 2.x anonymous method + implicit construction:
//
Person[] subset =
    Array.FindAll(people, delegate(Person p) { return p.LastName.StartsWith("D"); });

...which can also be rewritten as...

// .NET 3.x lambda expression:
//
Person[] subset = Array.FindAll(people, p => p.LastName.StartsWith("D"));

This progression through the historical options for using delegates, coupled with reviewing the IL produced by the C# compiler for each of the above examples to see how they’re equivalent, makes it pretty easy to calibrate one’s eyeball in order to read & understand lambda expressions.  But once we reached the lambda expression syntax, the class started to ask a few questions that all started out “So does that mean you can (insert crazy use of lambda expressions here)?”; to which the answer was invariably “yes”.

 

So during a layover on my trip home, and in the spirit of previous obfuscated programming contests, I decided to see how many ways I could (ab)use anonymous methods and lambda expressions to rewrite the canonical “Hello, world.” program using Visual Studio 2008.

 

Here’s what I came up with:

using System;
using System.Runtime.Remoting.Messaging;
using System.Threading;

class Program
{
  static void Main()
  {
    Console.WriteLine("Hello, world.");

    ((ThreadStart)delegate { Console.WriteLine("Hello, world."); })();
        
    ((ParameterizedThreadStart)delegate(object s) { Console.WriteLine(s); })(
        "Hello, world."
    );
        
    ((ParameterizedThreadStart)(s => Console.WriteLine(s)))("Hello, world.");
        
    (new Thread(s => Console.WriteLine(s))).Start("Hello, world.");
        
    ((ParameterizedThreadStart)(s => Console.WriteLine(s))).BeginInvoke(
      "Hello, world.",
      ar => ((ParameterizedThreadStart)((AsyncResult)ar).AsyncDelegate).EndInvoke(ar)
      ,null
    ).AsyncWaitHandle.WaitOne();
        
    ((ParameterizedThreadStart)(
      s => {
        Thread.CurrentThread.IsBackground = false;
        Console.Write(s);
      })).BeginInvoke(
        "Hello,",
        ar => {
          Console.WriteLine(ar.AsyncState);
          ((ParameterizedThreadStart)((AsyncResult)ar).AsyncDelegate).EndInvoke(ar);
        },
        " world."
      ).AsyncWaitHandle.WaitOne();
  }
}

I’m not yet sure what this says about my mental health :-)


Posted Jun 30 2008, 07:48 PM by mike-woodring

Comments

David Douglass wrote re: Fun with Anonymous Delegates & Lambda Expressions
on 07-01-2008 6:45 PM

You show .NET 1.x using a generic.  Generics were introduced with .NET 2.0.

mike-woodring wrote re: Fun with Anonymous Delegates & Lambda Expressions
on 07-03-2008 9:09 AM

I never said I was showing ".NET 1.x code".  I said I was showing ".NET 1.x delegate syntax" :-)  I used .NET 2.0 generics (Array.FindAll<T> and Predicate<T>) because it makes the rest of the code so much simpler, and lets me focus on the delegate syntax itself (and how it's evolved since .NET 1.x).

Bjorn Reppen wrote re: Fun with Anonymous Delegates & Lambda Expressions
on 07-10-2008 10:43 AM

IMHO FindAll is one of the worst inventions of the .net team..

Poor garbage collectors..

My question is: WHY do you want to find all.. and then replace the call to FindAll with the answer to that question..

IList Performance Decrease « Tales from a Trading Desk wrote IList Performance Decrease &laquo; Tales from a Trading Desk
on 07-16-2008 4:57 PM

Pingback from  IList Performance Decrease « Tales from a Trading Desk

Sean Chase wrote re: Fun with Anonymous Delegates & Lambda Expressions
on 08-28-2008 2:50 PM

First of all, my bug found the pizza before that other guy's did - the contest client tells lies imo.

Second, both of those Begin/EndInvoke examples make my head hurt. Nice job on those sir!

Third, I still have a copy of your Win32 multithreading book in my book cabinet.

^^^ true story   :)

Add a Comment

(required)  
(optional)
(required)  
Remember Me?