This blog is no longer updated. Feel free to copy any useful information to other blogs or wikis. Thanks.


Learning lambda expressions for XNA GS developers

October 1st, 2009 | 4 comments

I decided I wanted to do a bit of a tutorial on lambda expressions since someone on Twitter mentioned it. I’m not a master of the syntax, but I do use lambdas extensively in my code so I figured I can at least provide an introductory look at lambdas, their usages, and some examples of their use in code for XNA Game Studio developers.

First of all, what is a lambda expression?

A lambda expression is, at its core, a new way to write an anonymous delegate. Basically lambda expressions and anonymous delegates are ways of creating unnamed methods that get stored in a delegate type. What this means is first you must understand delegates. I’ll just refer you to this page and wait until you return.

Back already? Good. Let’s move on then. As that post showed, you can create a standard class method (or static method; both are acceptable) and assign them to delegates. An anonymous delegate is a way of creating a delegate without a standard method being defined. So to replicate one of their examples, here’s how you could create that add delegate:

Calculate add = delegate(int a, int b) { return a + b; }

So now you’ve created a delegate method without any actual method defined. This is an anonymous delegate. Be aware that this will create garbage, so I generally only use them when performance isn’t key or I store the delegate object itself for reuse. You probably don’t want to create hundreds of these per frame in your game or you’ll get hit with garbage collections.

Now you’ve seen an anonymous delegate. What, then, does a lambda look like? Well, to do the same thing as above, this is what it looks like with a lambda expression:

Calculate add = (a, b) => a + b;

Wow, isn’t that concise? Before moving on I’ll again just note that since lambda expressions are a form of anonymous delegate, they also allocate each time you use them. So either keep these tricks for places where performance isn’t key, you aren’t calling it a lot, or store that in a delegate for reuse. I don’t want to scare you; I use lambdas quite a bit in my own code with no real big perf hit, but I feel obligated to point out that this does allocate an object which does make it a place where garbage can be an issue.

Now let’s talk about this lambda expression thing. As you can see we no longer have the word “delegate” in there, making this already eight characters less to type. Beyond that, there is also type inference happening. This means that the compiler looks at the Calculate delegate and sees that the two parameters are both int values, so it knows that ‘a’ and ‘b’ (my two parameters) in my lambda expression are both of type int, making that another six (or eight if you count the spaces) characters that you don’t have to type.

Lambda expressions can also infer a return value type and therefore I don’t even need to explicitly say “return” in the expression. Because the Calculate delegate returns a value and my lambda expression is just a single statement, it knows to return that result. This doesn’t work, however, if you add braces around the expression (which is required if you want to have multiple statements in the expression). See this little snippet:

// we added braces, must have "return"
Calculate add1 = (a, b) => { return a + b; };

// we wanted more statements, so we had to add braces,
// therefore "return" is required
Calculate add2 = (a, b) =>
{
   int c = a + b;
   return c;
};

Now we have seen a few examples. Another example is a lambda expression that doesn’t have parameters. These are also easy and just mean you remove the parameters from the expression. Let’s use the System.Action delegate as an example:

Action something = () => { /* some code */ };

And if we wanted a single parameter, the parenthesis are optional:

Action<int> something = a =>
{
   // some code where 'a' is an int parameter
}

At this point I’m sure you’re sold. Lambda expressions are awesome. But what can we use them for in a real game? Here are some examples:

In my timing and interpolation code, I frequently use lambdas to define behaviors in line when creating timers or interpolators. So when creating a Timer that exits the game, I would simply write this:

Timer.Create(1f, false, t => Exit());

You can also use lambdas for event handlers, since event handlers are, themselves, just a form of delegate. A common thing for me is to have a MenuItem class that has an Activated event for my menus. So I could use a lambda to handle that event:

MenuItem item = new MenuItem("Play");
item.Activated += (s, e) => ScreenStack.Push(new GamePlayScreen());

Another use is for callbacks for things like the Guide methods. Let’s say you wanted to use the Guide’s BeginShowMessageBox to prompt a user before they exited the game, to make sure they wanted to. You could use a lambda for the asynchronous callback instead of making a regular method:

Guide.BeginShowMessageBox(
   "Are you sure?",
   "Are you sure you want to exit the game?",
   new[] { "Yes", "No" },
   1,
   MessageBoxIcon.None,
   result =>
   {
      int? response = Guide.EndShowMessageBox(result);
      if (response.HasValue && response.Value == 0)
         Exit();
   },
   null);

And lastly, let’s say we have a List of a Sprite class and wanted to sort them based on the bottom of their Bounds rectangle (a common thing when doing a top-down RPG to make sure sprites lower on the screen are drawn last and thus on top of the other sprites). We could use a lambda to pass to the Sort method to handle this logic for us:

sprites.Sort((s1, s2) => s1.Bounds.Bottom.CompareTo(s2.Bounds.Bottom));

I think that’s probably enough examples. :)

Again, a lambda expression is just another way of writing an anonymous delegate, both of which are just ways of writing methods inline rather than writing a normal class or static method. Sometimes they make sense to use and sometimes they don’t, but they’re definitely a nice tool to keep in your toolbox. Hopefully this long post has helped you learn something new. :)

  1. February 14th, 2010 at 10:53
    Quote | #1

    Cool post.
    Is there any way I can receive n parameters on my delegate function?

    So I could do something like

    Calculate add1 = (a, b) => sum();

    and also

    Calculate add1 = (a, b, c) => sum();

    Thanks

  2. February 14th, 2010 at 10:53
    Quote | #2

    Cool post.
    Is there any way I can receive n parameters on my delegate function?

    So I could do something like

    Calculate add1 = (a, b) => sum();

    and also

    Calculate add1 = (a, b, c) => sum();

    Thanks

  3. February 14th, 2010 at 10:56
    Quote | #3

    Given that the Calculate delegate is defined (in the linked post) as:

    public delegate int Calculate (int value1, int value2);

    No, you can’t. Calculate requires two input values and a single return. You could define another delegate type to have more parameters, but not with the Calculate delegate as defined.

  4. February 14th, 2010 at 10:56
    Quote | #4

    Given that the Calculate delegate is defined (in the linked post) as:

    public delegate int Calculate (int value1, int value2);

    No, you can’t. Calculate requires two input values and a single return. You could define another delegate type to have more parameters, but not with the Calculate delegate as defined.

Comments are closed.