4

Is there any way at all to achieve the use of downstream delegate definitions in an abstract parent class?

Delegates, like types, can't be overridden:

public abstract class ActionIssuerSimple
{
    public delegate void ActionHandler();
    ...
    public void Subscribe(ActionHandler handler) { ... }
}

public abstract class ActionIssuer<TAction> : ActionIssuerSimple
{
    public override delegate void ActionHandler(TAction parameter);
    ...
}

The above gives the error "delegate cannot be override"

The goal is, given an example of SillyIssuer : ActionIssuer<SillyAction>, for me to be able to use sillyIssuer.Subscribe((SillyAction action) => { ... }); (in addition to using ActionIssuerSimple for actions that can run handlers with the signature () => { }. Because C# doesn't support using downstream Delegate definitions in an abstract class, neither through abstract, generic type parameters, nor override, I can't quite find a way to do this without either:

  1. Copying all of the subscription functionality from ActionIssuerSimple into ActionIssuer. This is undesirable because it isn't DRY. Most of the code in ActionIssuerSimple revolves around manipulating a list of ActionHandlers.
  2. Having all ActionIssuers that don't need to pass an Action object pass one anyways, something like an int to reduce cost. This isn't desirable because it uses up unnecessary memory bandwidth in a high-traffic core loop for a performance-critical application. It also leaves me with a swath of unused parameter warnings in the ActionHandler methods.
M-Pixel
  • 3,501
  • 2
  • 16
  • 27

3 Answers3

2

It would be possible to use the desired delegate type as a type parameter for ActionIssuer turned into a generic class.

Codor
  • 17,447
  • 9
  • 29
  • 56
  • Unfortunately, there's no way to restrict the type parameter to be a delegate, because C# doesn't allow `where TActionHandler : Delegate`. Without such a restriction, calling `subscriber(action);` wouldn't be possible (since `subscriber` could be a class instance). – M-Pixel Aug 04 '15 at 06:51
2

The reason delegates cannot be overridden is seen in the compiled assembly:

.class auto ansi sealed nested public ActionHandler
   extends [mscorlib]System.MulticastDelegate
{
} // end of class ActionHandler 

You see, ActionHandler is not a 'real field' of the class - it's just a nested sealed class! :D

shay__
  • 3,815
  • 17
  • 34
  • Thanks, that makes a lot of sense. Delegates should be thought of as classes, then. It seems the best approach, treating it as a class, is to use a Type Parameter with one of the workarounds listed here http://stackoverflow.com/questions/191940/c-sharp-generics-wont-allow-delegate-type-constraints – M-Pixel Aug 04 '15 at 17:32
1

Not sure what you're trying to achieve. You can override a Property/Method not Types. Delegate is a type and what does it mean to override a delegate?

I guess you need a generic delegate which you can take as a parameter in ActionIssuer<TAction>.Subscribe method.

public delegate void ActionHandler<TAction>(TAction parameter);

public abstract class ActionIssuer<TAction>
{
    public void Subscribe(ActionHandler<TAction> handler) { ... }
    ...
}

Then you could do

sillyIssuer.Subscribe((SillyAction action) => { ... });
Sriram Sakthivel
  • 72,067
  • 7
  • 111
  • 189
  • Is there any way for this approach to also allow for paramater-less ActionHandlers? This appears to be undesirable option #2 from my original post. – M-Pixel Aug 04 '15 at 07:02
  • @Qwertman How that will be used, What does the call site look like? Can you show some example of how you'd like to use it. – Sriram Sakthivel Aug 04 '15 at 10:28