views:

226

answers:

1
    Action<SPItemEventProperties> deleteAction = DeleteWorkspace;
    AsyncCallback deleteDone = deleteAction.EndInvoke;
    SPSecurity.RunWithElevatedPrivileges(() => deleteAction.BeginInvoke(properties, deleteDone, null));

So this is suppose to call DeleteWorkspace Asynchronously and then call EndInvoke when its done, I wrote it but I am not positive it will work properly. I stepped through and it appears to work but the syntax is making me second guess myself cause I have never seen it done like this on the net...

Comments?

+1  A: 

It should work, but to really understand it let's pretend it were written like this:

void RunAsync<T>(Action<T> action)
{
    AsyncCallback Done = action.EndInvoke;
    SPSecurity.RunWithElevatedPrivileges(() => action.BeginInvoke(properties, Done, null));
}

RunAsync(DeleteWorkspace);

Note that in the code above, it looks like the 'Done' callback will go out of scope right away. However, the compiler will capture (close over) it with a closure, so that it's available when needed.

Joel Coehoorn
Thanks Joel that was my question, I wasn't positive that it would force the use of a closure. How can you verify that btw? Thanks for the answer though!
emalamisura
Any time you pass a variable to a lambda, it uses a closure. I know it's tricky to start noticing that.
Joel Coehoorn
Yup, that's absolutely the case. For fun, have a look at the decompiled code - that "local variable" will actually be a member of a new class the C# compiler has created for you.
Jon Skeet
Mind you, you don't really *need* the "local" variable anyway. You could use deleteAction.EndInvoke directly in the lambda: () => deleteAction.BeginInvoke(properties, deleteAction.EndInvoke, null) should be fine. Without looking, I can't remember whether you'd have to cast it to AsyncCallback or not, but I *suspect* not.
Jon Skeet