Search Unity

C# Generic Event Manager with Inheritance problems

Discussion in 'Scripting' started by mr malee, Nov 9, 2012.

  1. mr malee

    mr malee

    Joined:
    Sep 19, 2012
    Posts:
    25
    Hi, so I've been trying to implement a simple event manager in C#. It works, but I seem to have hit a problem with using generics and inheritance. Some code might explain my problem better:

    This represents a simple event manager, create a generic delegate that assumes a type safe sender.
    And a safe dispatch method.
    Code (csharp):
    1.  
    2. public delegate void EventHandler<T>(T sender);
    3.  
    4. public class EventManager<T> {
    5.  
    6.     public static void Dispatch(EventHandler<T> evt, T sender) {
    7.  
    8.         if (evt != null) {
    9.  
    10.             evt(sender);
    11.         }
    12.     }
    13. }
    14.  
    Here are two classes which use the event manager to dispatch their events.

    Code (csharp):
    1.  
    2. public class BaseClass : MonoBehaviour {
    3.  
    4.     public event EventHandler<BaseClass> MyEvent;
    5. }
    6.  
    7. public class SubClass : BaseClass {
    8.  
    9.     public event EventHandler<SubClass> MyEvent;
    10.  
    11.     void Start() {
    12.  
    13.         EventManager<BaseClass>.Dispatch(MyEvent, this); //Won't Compile
    14.         EventManager<BaseClass>.Dispatch(MyEvent, (BaseClass)this); //Won't Compile
    15.         EventManager<BaseClass>.Dispatch(MyEvent, this as BaseClass); //Won't Compile
    16.  
    17.         EventManager<SubClass>.Dispatch(MyEvent, this); //Will Compile
    18.     }
    19. }
    20.  
    I don't understand why the first 3 dispatch calls don't compile. Clearly SubClass inherits from BaseClass, so it is a BaseClass. This cannot be changed after runtime, so why is there a problem? Why Can't I cast to BaseClass?

    The problem I'm facing is getting all objects in my game as a "BaseClass" and trying to listen to "MyEvent" defined inside it. If sub classes cannot dispatch this event, this means I need to check for all specific types when registering events.

    One solution is to write a "Dispatch" method in the BaseClass which runs the event, and call Dispatch from the sub class, but it's ugly and means I have to write one of these methods for every class which might dispatch some event.
     
  2. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,537
    1) your 'MyEvent' in SubClass already exists because it was inherited from BaseClass. This is called shadowing, it can be done, bet can cause issues.

    2) Generic class static members is usually considered code smell.
    http://msdn.microsoft.com/en-us/library/ms182139(v=vs.110).aspx

    3) mono/.net already has an event model built into it... what is this static EventManager attempting to accomplish that it doesn't? From the looks of your code, the built in model does what you want.

    4) you're actually using the event model that exists. And you're attempting to call said event from outside of the class. An 'event' can only be called by the class that owns the event... this is one of the defined natures of 'event's in .Net that makes them unique from regular old delegates (events are special types of delegates). This here is why your lines you marked as "//Won't Compile"... won't compile. You're attempting to use an event object in a way that is not allowed.
     
    Last edited: Nov 9, 2012
  3. mr malee

    mr malee

    Joined:
    Sep 19, 2012
    Posts:
    25
    Ok thankyou, I wasn't aware that events had that requirement.

    My intention was to create a generic implementation of events while still adhering to type safe methods.
     
  4. kablammyman

    kablammyman

    Joined:
    Nov 22, 2010
    Posts:
    507
    +1