Reputation: 3457
This problem is sort of complex for me, I'm not a C# guru.
Basically I have a Queue of some tasks I would like to handle. I want to be able to push various methods to that Queue, they will do different things, but all will take one string as a parameter. The question: how can I achieve this with the use of delegates? I'm not sure how to do this so the compiler doesn't throw any errors.
The code that more or less ilustrates what I want to do:
delegate void Del(string);
Queue<Del> Q = new Queue<Del>();
public DT()
{
string foo = "bar";
Q.Enqueue((foo) =>
{
//do some stuff
});
}
//somewhere else I constantly check the queue and run the tasks
This design may seem bizarre, but in that regard I'm sure what I'm doing.
So, this gives a compiler error that a local variable foo cannot be declared. Of course I don't want to declare it, I want to sort of pass it to the function being pushed on the queue. What should I do?
I hope you understand my problem. Thank you.
Upvotes: 0
Views: 2970
Reputation: 283684
The delegate type forms the signature for the final call. Since you've said the string is provided when you enqueue it, the signature for the call is
delegate void Del();
Queue<Del> Q = new Queue<Del>();
Now to enqueue:
public DT()
{
string foo = "bar";
Q.Enqueue(() =>
{
//do some stuff using foo
});
}
The value of foo
is in scope inside the lambda, and will be captured into the delegate before it is enqueued. This is called a closure.
Note that you could just use the predefined delegate type System.Action
instead of creating your own.
Upvotes: 2
Reputation: 236248
Just use different name of lambda argument (currently it conflicts with local foo
variable declaration):
Q.Enqueue(f => {
//do some stuff
});
Then later you can get delegate from queue an pass parameter to it:
Q.Dequeue()(foo);
If you want to capture value of foo
variable, then just use it in do some stuff part. In this case you probably want delegate with signature, which does not accept any input parameters:
Queue<Action> actions = new Queue<Action>();
string foo = "bar";
actions.Enqueue(() => Console.WriteLine(foo));
actions.Dequeue()();
BTW: You don't need to create these delegates - use existing Action<T>
or Action
delegates.
Upvotes: 3