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