user4520
user4520

Reputation: 3457

Queue of delegates with a parameter

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

Answers (2)

Ben Voigt
Ben Voigt

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

Sergey Berezovskiy
Sergey Berezovskiy

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

Related Questions