0

I'm attempting to build a recurring programming pattern into a generic class for code re-use. Part of this pattern thread-safely subscribes/unsubscribes to a delegate as needed during asynchronous operations (multicast delegate used as event).

The following code does not compile. The problem I'm facing is that C# allows me to pass a delegate as method argument, but anywhere inside MyWorker class the subscribe +=,-= operations cause errors. (Works fine on the same delegate from outside).

[Operator '+=' cannot be applied to operands of type 'delegateT' and 'method group']

Syntactical errors? delegate scope limitation? is this disallowed by the language?

public class MyWorker<delegateT,argT>
{
    private delegateT mDelegate;

    public MyWorker(delegateT d)
    {
        mDelegate = d; //save delegate (reference?) for use later
    }

    public void DoWorkAsync()
    {
        mDelegate += m_subscriber; //ERROR: Operator '+=' cannot be applied to operands of type 'delegateT'...

        //...Do some work that causes delegate to fire...

        mDelegate -= m_subscriber; //ERROR: Operator '-=' cannot be applied to operands of type 'delegateT'...
    }

    private void m_subscriber(argT arg)
    {
        Console.WriteLine("Received: " + arg.ToString());
    }
}

Note that generics do not seem to be the cause; I've tried using static types instead with the same result. I've also tried passing delegate with the 'ref' keyword to make sure i'm storing and referencing the original object rather than a local copy...maybe a secondary issue, but one step at a time.

[UPDATE]

OIC, inability to constrain Delegate type seems to be a major issue here, and prevents generic usage the way I'm doing it. Thanks for pointing that out Ron.

To clarify the original intent:
I use delegates for internal events; more flexibility than strict 'event' type. I'm searching for some way to pass a delegate (ref?) to MyWorker class at runtime. Then MyWorker performs some background tasks which subscribe and unsubscribe as necessary to receive events during operation, before finally exiting for garbage collection. I do this for 30+ nearly identical tasks/events, which is why creating a reusable (generic?) class is highly desirable.

Delegates in my system have a strict form such as:

delegate void delegateEvent1(Class1 arg);
delegate void delegateEvent2(Class2 arg);
...
delegate void delegateEventN(ClassN arg);

Plan B is to pass Action delegates to subscribe and unsubscribe from within MyWorker. This is quite a bit messier as it requires 2 Actions<> to be created for each invocation rather than just cleanly passing the desired delegate.

Open to any suggestions...

Sparky
  • 1
  • 1
  • Maybe you should explain what you are trying to achieve here. Your code does not make sense. The reason for the error is because the compiler has no idea what type mDelegate is. You can give it a hint by using a [generic type constraint](https://msdn.microsoft.com/en-us/library/bb384067.aspx). But delegate is not a type. Consider using an Action<> or Func<> instead. – KiwiPiet Nov 05 '15 at 21:39
  • While you can use a delegate as a generic type, you can't constrain it, so the compiler has no way of knowing that `TDelegate` is a delegate type, for all it knows, its a struct or a class. See http://stackoverflow.com/questions/191940/c-sharp-generics-wont-allow-delegate-type-constraints after that you will need to do a cast after checking the delegate type. – Ron Beyer Nov 05 '15 at 21:58

1 Answers1

0

It's not because you named your generic parameter delegateT compiler knows it's some delegate type and so it can't know that some += operator exists on that type. It would need some generic constraint to enforce this ; but AFAIK that's not possible in C#

As KiwiPiet pointed in comment you can maybe try to add a constraint for some delegate type though
As pointed by Ron Beyer in comment it's also not possible to constraint to some delegate type too

Sehnsucht
  • 5,019
  • 17
  • 27
  • You can't add constraints for delegate types, its one of the few types you can't constrain to (like Enum). – Ron Beyer Nov 05 '15 at 21:59
  • I knew about delegate constraint (and said it) but wasn't so sure about a constraint like `where T : Func` and KiwiPiet comment didn't helped so I wrote it in case (with a maybe) – Sehnsucht Nov 05 '15 at 22:13