I know that .NET lambda expressions can capture outer variables.
However, I have seen it a lot of times that variables are passed explicitly to the lambda expression as a parameter, and the .NET library also seems to support that (e.g. ThreadPool.QueueUserWorkItem).
My question is that what are the limitations of these captures? How about lambdas that are actually executed on a different thread than the one they were created on (e.g. ThreadPool.QueueUserWorkItem, or Thread), or lambas that act as callbacks (i.e. invoked at a later time)?
Generally, when should I rely on captured variables, and when to use explicit parameters? For example:
public void DoStuff()
{
string message = GetMessage();
ThreadPool.QueueUserWorkItem(s => SendMessage(message)); // use captured variable
// -- OR --
ThreadPool.QueueUserWorkItem(s =>
{
string msg = (string)s;
SendMessage(msg);
}, message); // use explicit parameter
}
Thank you!
Update: fixed the second ThreadPool.QueueUserWorkItem example.
I think in your first example., you mean
In your second item, where does the parameter
scome from? I think you meanNow, these two both work equivalently, but
In the first case: the parameter
messageis copied from the scope ofthis
DoStuffmethod and storeddirectly in your lambda expression
itself, as a closure. The lambda has
keeps a copy of
message.In the second case:
messageis sentto the
Queue, and the queue keepshold of it (along with the lambda),
until the lambda is called. It is
passed at the time of running the
lambda, to the lambda.
I would argue that the second case is more programmatically flexible, as it could theoretically allow you to later change the value of the
messageparameter before the lambda is called. However the first method is easier to read and is more immune to side-effects. But in practice, both work.