Thursday, September 25, 2008

Anonymous functions rock!

I've been working on a project in C# 3.0 lately and I have to say that I am absolutely loving anonymous functions. I've found them most helpful working on my multithreaded code and I love them for two reasons.

First, it lets me keep related code even closer together. The code I'm doing has a lot of set up to do a task, then run the task in the background work and by using an anonymous function right inline with the setup / start the thread code, it's easy to see an overall picture of exactly what's happening.

My code went from looking like this (note all the whitespace between actual executing code):
void doSomething()
{
  // setup code
  ThreadPool.QueueUserWorkItem(doExpensiveOperation, null);
}

void doExpensiveOperation(object state)
{
  // Do the actual work
}


To this:
void doSomething()
{
// setup code
  ThreadPool.QueueUserWorkItem(delegate(object state)
    {
      // Do the actual work
    }, null);
}


As if making my code smaller and easier to see wasn't enough, using anonymous functions in this way also gets me closures. The great thing about closures is that it means you don't have to pass a whole lot of data to your function that actually does the work. The easiest thing is for me to show you an example...

In the past where I would have had to do this:

private class ExpensiveOperationData
{
  public Foo fooObj;
  public Bar barObj;
}

void doSomething(Foo fooObj, Bar barObj)
{
  ExpensiveOperationData data = new ExpensiveOperationData();
  data.fooObj = fooObj;
  data.barObj = barObj;

  ThreadPool.QueueUserWorkItem(doExpensiveOperation, data);
}

void doExpensiveOperation(object state)
{
  ExpensiveOperationData data = (ExpensiveOperationData)state;
  // Do the operation using data.fooObj and data.barObj;
}


Now I can do this:

void doSomething(Foo fooObj, Bar barObj)
{
  ThreadPool.QueueUserWorkItem(delegate(object junk)
  {
    // Do the operation using fooObj and barObj;
  }, data);
}


I can't get over how nice it is to get rid of all those extra hoops I used to jump through just to get the data I wanted to work on into the thread.

No comments: