31

Why can't I add a delegate to my interface?

0

7 Answers 7

34

You can use any of these:

public delegate double CustomerDelegate(int test);
public interface ITest
{
    EventHandler<EventArgs> MyHandler{get;set;}
    CustomerDelegate HandlerWithCustomDelegate { get; set; }
    event EventHandler<EventArgs> MyEvent;
}
4
  • 5
    Why create CustomerDelegate when you can just use Func<int, double>? Commented Mar 5, 2009 at 1:28
  • 1
    I know, I was just illustrating that you can use pretty much anything :)
    – eglasius
    Commented Mar 5, 2009 at 2:31
  • 9
    It gets difficult to understand parameters like Func<int, string[], bool>. Much more meaningful to have a name for that signature. Commented Dec 4, 2012 at 4:07
  • 4
    When working across COM you actually have to use your own delegate as you cannot marshal generic types like Func<>, EventHandler<>, Action<>.
    – Kyle
    Commented Dec 6, 2013 at 19:01
24

A Delegate is just another type, so you don't gain anything by putting it inside the interface.

You shouldn't need to create your own delegates. Most of the time you should just use EventHandler, Func, Predicate, or Action.

May I ask what your delegate looks like?

1
  • 2
    This answer actually also solved my problem that I could never find a nice way to use delegates in the situations where I wanted to use them. I.e. don't use 'm :). Commented Sep 17, 2012 at 10:15
11

this is a delegate TYPE decalaration...

public delegate returntype MyDelegateType (params)

this cant be declared in an interface as it is a type declaration

however using the type declaration above you CAN use a delegate instance

MyDelegateType MyDelegateInstance ( get; set;)

so delegate instances are OK but delegate type declarations aren't (in an interface)

1
  • Best answer so far. To the point. I much I love when people goes to the point instead of writing speeches. Commented Nov 24, 2016 at 23:09
7

A Delegate is a type which can't be declared in an interface. You might want to either use an event(if appropriate) or declare a delegate outside the interface but in the same namespace.

This link may help- When to Use Delegates Instead of Interfaces

5

The documentation clearly says that you can define a delegate in an interface:

An interface contains only the signatures of methods, delegates or events.

MSDN: interface (C# Reference)

However, in the remarks on the same page it says that an interface can contain signatures of methods, properties, indexers and events.

If you try to put a delegate in an interface, the compiler says that "interfaces cannot declare types."

The Ecma-334 standard (8.9 Interfaces) agrees with the remarks on that page and the compiler.

1
  • 2
    That looks like an error in MSDN. That should be "the signatures of methods, properties or events", shouldn't it? Commented Mar 5, 2009 at 0:12
1

As others have mentioned, you can only define delegates outside of the interface.

There is little to nothing wrong w/ using delegates. Personally I think that Func<int, double> is less desirable than using delegates:

  1. You cannot name the arguments, so the argument meaning can be ambiguous
  2. It is old news that Events are not thread safe, thus the following code is not ideal:

    if (MyFuncEvent != null)
    {
        MyFuncEvent(42, 42.42);
    }
    

    See: http://kristofverbiest.blogspot.com/2006/08/better-way-to-raise-events.html

    The safer code is:

    MyFuncEventHandler handler = MyFuncEvent;
    if (handler != null)
    {
        handler(42, 42.42);
    }
    
  3. You have to duplicate the signature of the event if you want to save it to a variable (or you could use var, which I dislike). If you have lots of arguments then this could get very tedious (again, you could always be lazy and use var).

    Func<int, double, string, object, short, string, object> handler = MyFuncEvent;
    if (handler != null)
    {
        handler(42, 42.42, ...);
    }
    

Delegates save you from having to duplicate the signature of the method/event every time you want to assign it to a variable type.

1
  • 1
    However, note that you can name the arguments at the call site of a lambda function (but only if there are more than two):Action<int, int> f = (int i, int j) => { }; /* same as, */ var g = (Action<int, int>)((i, j) => { }); Oddly, you can't use 'var' when using the former syntax (which is when it is least needed). Commented Jun 27, 2012 at 21:14
1

An interface method can accept a delegate as a parameter, no issues. (Maybe I'm not seeing the problem?) But if the intention is to specify an outbound call in the interface, use an event.

There are so many little details, it's a lot easier to just show some code instead of trying to describe it all in prose. (Sorry, even the code sample is a bit bloated...)

namespace DelegatesAndEvents
{
    public class MyEventArgs : EventArgs
    {
        public string Message { get; set; }
        public MyEventArgs(string message) { Message = message; }
    }

    delegate void TwoWayCallback(string message);
    delegate void TwoWayEventHandler(object sender, MyEventArgs eventArgs);

    interface ITwoWay
    {
        void CallThis(TwoWayCallback callback);

        void Trigger(string message);
        event TwoWayEventHandler TwoWayEvent;
    }

    class Talkative : ITwoWay
    {
        public void CallThis(TwoWayCallback callback)
        {
            callback("Delegate invoked.");
        }

        public void Trigger(string message)
        {
            TwoWayEvent.Invoke(this, new MyEventArgs(message));
        }

        public event TwoWayEventHandler TwoWayEvent;
    }

    class Program
    {
        public static void MyCallback(string message)
        {
            Console.WriteLine(message);
        }

        public static void OnMyEvent(object sender, MyEventArgs eventArgs)
        {
            Console.WriteLine(eventArgs.Message);
        }

        static void Main(string[] args)
        {
            Talkative talkative = new Talkative();

            talkative.CallThis(MyCallback);

            talkative.TwoWayEvent += new TwoWayEventHandler(OnMyEvent);
            talkative.Trigger("Event fired with this message.");

            Console.ReadKey();
        }
    }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.