Delegates and inheritance in c#

10,412

Solution 1

You could replace next=DoMethod; with next= ()=>Method(); which is essentially the same, but doesn't require you to define an extra method on your class.

Solution 2

In your first example, you are assigning the result of Method(); to the delegate, so naturally that means that the Method method (ahem) will be executed at that point to assign a value. Ignoring the fact that Method is void (which won't compile).

In the second example, you are assigning a reference to the method (which doesn't have to be an instance method) to the delegate, which allows you to execute the del at a later stage.

The following works for me:

class Program
{
    static void Main(string[] args)
    {
        var baseClass = new BaseObject();
        baseClass.Execute();

        var derivedClass = new DerivedObject();
        derivedClass.Execute();

        Console.ReadKey();
    }
}

class BaseObject
{
    public delegate void SomethingDelegate();
    public SomethingDelegate Delegate;

    public BaseObject()
    {
        Delegate += Something;
    }

    public virtual void Something()
    {
        Console.WriteLine("Base Class");
    }

    public void Execute()
    {
        Delegate();
    }
}

class DerivedObject : BaseObject
{
    public override void Something()
    {
        Console.WriteLine("Derived Class");
    }
}

In the above example, the fact that the delegate pointer is expressed as a pointer to the Something method (of BaseObject), because the method is virtual, the call is still correctly dispatched to the overriden Something method (of DerivedObject).

Are you not seeing the same behaviour?

Solution 3

No, Execute will run the inherited method. After making some correction to the code I could test it:

public class BaseObject {
  public delegate void del();

  public BaseObject() {
    next = Method;
  }

  public del next;
  public void Execute() {
    next();
  }

  public virtual void Method() {
    Console.WriteLine("base");
  }
}

public class InheritedObject : BaseObject {

  override public void Method() {
    Console.WriteLine("inherited");
  }

}

Called:

(new InheritedObject()).Execute();

Output:

inherited
Share:
10,412
Krzysztof Bociurko
Author by

Krzysztof Bociurko

Updated on June 04, 2022

Comments

  • Krzysztof Bociurko
    Krzysztof Bociurko almost 2 years

    I have a bit of a problem with inheritance of delegates. Delegate as far as i understand is a pointer to a pair: an instance and a method, the thing is this is the method referenced in the creation of the delegate, and not affected by inheritance. So, this won't work:

    public class BaseObject {
      public delegate void del();
    
      public BaseObject() {
        next=Method;
      }
    
      public del next;
      public void ExecuteNext() {
        next();
      }
    
      public virtual void Method() {
        Debug.Log("BASE");
      }
    }
    
    public class InheritedObject:BaseObject {
      override public void Method() {
        Debug.Log("INHERITED");
      }
    }
    ...
    
    (new InheritedObject()).ExecuteNext();
    

    Execute runs the base Method(), I want it to run the inherited Method(). I have found some way around, but it is inefficient, distracting and very error prone, anyway here's the current working version that I'd like to get rid of:

    class BaseObject {
      public delegate void del();
    
      BaseObject() {
        next=DoMethod;     /// using DoMethod here
      }
    
      public del next;
      public void ExecuteNext() {
        next();
      }
    
    
      public void DoMethod() {    /// using DoMethod here
        Method();
      }
      public virtual void Method() {
        // do base
      }
    }
    
    class InheritedObject:BaseObject {
      override public void Method() {
        // do inherited
      }
    }
    
    ...
    
    (new InheritedObject()).Execute();
    

    This DoMethod aproach works but has many problems,

    1. lots of useless code
    2. error prone when using the class - easy to mistake obj.next=DoMethod with obj.next=Method
    3. error prone when inheriting the class - I have to remember to not to inherit the DoMethod, and lots of virtual and overrides.

    Any suggestions how can I do that better? Perhaps some annotation magic that does the DoMethod by itself? I've already thought of dictionaries - they aren't good here, they add even another level of confusion (Mono, .NET 2, Unity3d framework)