4

I can't find a way to implement delegate in interface

I want to get this:

public class SomeClass : ISomeInterface
{
    public delegate void SomeCallback();
    public SomeCallback callback;

    public void SomeMethod()
    {
         callback.invoke();
    }
}

public class MainClass
{
    void Callback() { Console.WriteLine("Callback"); }

    public void Start()
    {
         SomeClass s = new SomeClass();
         s.callback = Callback;
         s.SomeMethod();
    }
}

but in case when I create instance of the class "SomeClass" using interface:

public class MainClass
{

    void Callback() { Console.WriteLine("Callback"); }

    public void Start()
    {
         ISomeInterface s = new SomeClass();   // <<<----
         s.callback = Callback;                // here will be an error :(
         s.SomeMethod();
    }
}

Please, help me with it :)

  • Well, of course. If you are treating `s` as an `ISomeInterface`, it has no idea about anything to do with `SomeClass`. When you implement or extend `ISomeInterface`, your additions don't magically make it back upstream to the interface. If you want to use members you declared in `SomeClass`, you'll have to treat it as a `SomeClass`. – Glorin Oakenfoot Feb 18 '16 at 20:07
  • maybe there is some trick for that? i just want to get callbacks from objects created this way (using interfaces) – Vadim Vdovenko Feb 18 '16 at 20:10
  • it would be great if i could assign delegates using some method declared in interface – Vadim Vdovenko Feb 18 '16 at 20:12
  • You *can* use the `is` or `as` operators to check and see if your `ISomeInterface` variable is *actually* a `SomeClass`. However, I would ask why are you even treating your objects as an interface at that point, if you really need details of a concrete implementation? If you're simply wanting the callback to be part of the interface, then change its declaration to a property: `SomeCallback callback {get; set;}` – Glorin Oakenfoot Feb 18 '16 at 20:14
  • Could you tag this question to include the language. It may help you get more views... – Rick Smith Feb 18 '16 at 20:14
  • Sure :) "s" in this example can be any of several different classes that do same stuff in a different way. for example, it can be AndroidConnectionService or IOSConnectionService and both implement IConnectionService interface. i need to get callbacks from these objects without "asking" them about their classes – Vadim Vdovenko Feb 18 '16 at 20:22
  • ((SomeClass)s).callback = Callback; – Kevin Feb 18 '16 at 20:35
  • it is a good idea, but i have more than one callback and this code will grow :( – Vadim Vdovenko Feb 18 '16 at 20:40
  • If you want the callback to a property of the interface, then it needs to be declared in the interface. That's really the only way you can do what you're asking for. – Glorin Oakenfoot Feb 18 '16 at 21:01
  • can you please edit my code this way? – Vadim Vdovenko Feb 18 '16 at 21:04
  • https://gyazo.com/3cdbe1d3280e6f6f80ecd4f18df439d3 i cant implement this interface member correctly - it gives error all the time :( – Vadim Vdovenko Feb 18 '16 at 21:14

1 Answers1

5

Moving the callback to the interface is required if you want to use the callback without casing to a concrete type. Note that your current implementation has callback as a field. To declare it in an interface, you must make it a property.

Because properties are really methods, you must implement the property in your concrete class. Using an auto-property is fine for the implementation here.

Once you've made those changes, you can then set and call the callback using only the interface.

public delegate void SomeCallback();

public interface ISomeInterface {
    SomeCallback callback { get; set; }
    void SomeMethod();
}

public class SomeClass : ISomeInterface
{
    public SomeCallback callback { get; set; }

    public void SomeMethod()
    {
        callback.Invoke();
    }
}

public class MainClass
{
    void Callback() { Console.WriteLine("Callback"); }

    public void Start()
    {
        ISomeInterface s = new SomeClass();
        s.callback = Callback;
        s.SomeMethod();
    }
}
Glorin Oakenfoot
  • 2,455
  • 1
  • 17
  • 19