Delegates, Actions and Memory Allocations

I'm currently working on a chunk of code that requires minimum memory allocations.

I've noticed if I use a method for a parameter the compiler changes the code and creates a new Action, But if I use an anonymous method the compiler creates a delegate block , I'm aware that the new Action allocates memory , but I'm not so sure about the delegate. Will delegates allocate memory when used?

My Code

 bool workfinished = false;
    void DoWork()
    {

    MyMethod(  CallBack1Work ,()=>{ workfinished = false;});

    }

    void MyMethod(Action callback1 ,Action callback2)
    {

    }

    void CallBack1Work()
    {

    }

Compiler Version

bool workfinished = false;


        void DoWork{

        MyMethod( new Action( CallBack1Work ),delegate{ 
                                                      workfinished = false; 
                                                       });

        }
        void MyMethod(Action callback1 ,Action callback2)
        {

        }

        void CallBack1Work()
        {

        }

        void DoWork_b01()
        {
             workfinished = false;
        }

Thanks in advance!

Jon Skeet
people
quotationmark

If you use a lambda expression which doesn't capture anything, the compiler will generate a static field to cache it in. So use that, you can change the Action to an Action<YourClass> and call it with this. So:

class YourClass
{
    private bool workFinished;

    public void DoWork()
    {
        MyMethod(instance => instance.Callback1Work(),
                 instance => instance.workFinished = false);
    }

    private void MyMethod(Action<YourClass> callback1,
                          Action<YourClass> callback2)
    {
        // Do whatever you want here...
        callback1(this);
        // And here...
        callback2(this);
    }

    private void Callback1Work()
    {
       // ...
    }
}

That will only create delegate instances the first time DoWork is called on any instance. The delegates will then be cached for all future calls on all instances.

Admittedly this is all an implementation detail. You could always make it clearer:

class YourClass
{
    private static readonly Action<YourClass> Callback1 = x => x.Callback1Work();
    private static readonly Action<YourClass> Callback2 = x => x.workFinished = false;

    private bool workFinished;

    public void DoWork()
    {
        MyMethod(Callback1, Callback2);
    }

    ... code as before ...
}

It's worth actually profiling and benchmarking the code before you go to any of these lengths though.

Another alternative would be to stick to Action, but create instance variables for the delegates - so as long as you called DoWork multiple times on the same instance, you'd be okay:

class YourClass
{
    private readonly Action foo;
    private readonly Action bar;

    private bool workFinished;

    public YourClass()
    {
        foo = Callback1Work;
        bar = () => workFinished = false;
    }

    public void DoWork()
    {
        MyMethod(foo, bar);
    }

    public void MyMethod(Action callback1, Action callback2)
    {
        ...
    }

    private void Callback1Work()
    {
        ...
    }
}

people

See more on this question at Stackoverflow