Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unsubscribe from delegate passed through ref keyword to the subscription method?

I've got the following class:

public class Terminal : IDisposable
{
    readonly List<IListener> _listeners;

    public Terminal(IEnumerable<IListener> listeners)
    {
        _listeners = new List<IListener>(listeners);
    }

    public void Subscribe(ref Action<string> source)
    {
        source += Broadcast;
        //Store the reference somehow?
    }

    void Broadcast(string message)
    {
        foreach (var listener in _listeners) listener.Listen(message);
    }

    public void Dispose()
    {
        //Unsubscribe from all the stored sources?
    }
}

I've searched for a while and it appears that an argument passed with the ref keyword can't be stored. Trying to add the source argument to a list or to assign it to a field variable doesn't allow it to keep a reference to the actual delegate's original reference; so my questions are:

  • Is there a way to unsubscribe from all the sources without passing their references again?
  • If not, how can the class be changed in order to support it, but still maintain the subscription by passing a delegate through a method?
  • Is it possible to achieve it without using Reflection?
  • Is it possible to achieve it without wrapping the delegate/event in a class and then passing the class as a parameter for the subscription?

Thank you.

EDIT: It appears that without using a Wrapper or Reflection, there's no solution to the given problem. My intention was to make the class as much portable as possible, without having to wrap delegates in helper classes. Thanks everyone for the contributions.

like image 340
user1098567 Avatar asked Dec 14 '11 19:12

user1098567


People also ask

Are delegates passed by reference C#?

C# does not pass by reference unless you specify the ref keyword. However, since the value of a variable of a delegate type is a reference to a method, the value passed is a reference. Use the ref keyword and you pass a reference to the variable's store, not the method, thus it becomes possible to change its value.

What is delegate type in C#?

A delegate is a type that represents references to methods with a particular parameter list and return type. When you instantiate a delegate, you can associate its instance with any method with a compatible signature and return type. You can invoke (or call) the method through the delegate instance.

What will happen if a delegate has a non void return type?

When the return type is not void as above in my case it is int. Methods with Int return types are added to the delegate instance and will be executed as per the addition sequence but the variable that is holding the return type value will have the value return from the method that is executed at the end.


1 Answers

Edit: Ok, that was a bad idea, so back to the basics:

I recommend creating a wrapper class over an Action:

class ActionWrapper
{
    public Action<string> Action;
}

And restructuring your initial class to work with wrappers:

private ActionWrapper localSource;

public void Subscribe(ActionWrapper source)
{
    source.Action += Broadcast;
    localSource = source;        
}

public void Dispose()
{
    localSource.Action -= Broadcast;
}

Now you should get the desired results.

like image 152
Tudor Avatar answered Nov 15 '22 12:11

Tudor