views:

163

answers:

2

I'm curious to know whether a Lambda (when used as delegate) will create a new instance every time it is invoked, or whether the compiler will figure out a way to instantiate the delegate only once and pass in that instance.

More specifically, I'm wanting to create an API for an XNA game that I can use a lambda to pass in a custom call back. Since this will be called in the Update method (which is called many times per second) it would be pretty bad if it newed up an instance everytime to pass in the delegate.

InputManager.GamePads.ButtonPressed(Buttons.A, s => s.MoveToScreen<NextScreen>());
+2  A: 

Yes, it will cache them when it can:

using System;

class Program {
    static void Main(string[] args) {
        var i1 = test(10);
        var i2 = test(20);
        System.Console.WriteLine(object.ReferenceEquals(i1, i2));
    }

    static Func<int, int> test(int x) {
        Func<int, int> inc = y => y + 1;
        Console.WriteLine(inc(x));
        return inc;
    }
}

It creates a static field, and if it's null, populates it with a new delegate, otherwise returns the existing delegate.

Outputs 10, 20, true.

MichaelGG
+3  A: 

I was interested by your question because I had just assumed that this kind of thing would always generate a new object and hence to be avoided in code which is called frequently.

I do something similar so I thought I would use ildasm to find out what exactly is going on behind the scenes. In my case it turned out that a new object was getting created each time the delegate was called, I won't post my code because it is fairly complex and not very easy to understand out of context. This conflicts with the answer provided by MichaelGG, I suspect because in his example he makes use of static functions. I would suggest you try it for yourself before designing everything one way and later on finding out that you have a problem. ildasm is the way to go (http://msdn.microsoft.com/en-us/library/f7dy01k1.aspx), look out for any "newobj" lines, you don't want those.

Also worth using CLR Profile to find out if your lambda functions are allocating memory (http://www.microsoft.com/downloads/details.aspx?familyid=A362781C-3870-43BE-8926-862B40AA0CD0&amp;displaylang=en). It says it's for framework 2.0 but it also works for 3.5 and it's the latest version that is available.

Martin Sherburn