web-dev-qa-db-fra.com

Pourquoi ne puis-je pas mettre un délégué dans une interface?

Pourquoi ne puis-je pas ajouter un délégué à mon interface?

26
user73936

Vous pouvez utiliser n'importe lequel de ceux-ci:

public delegate double CustomerDelegate(int test);
public interface ITest
{
    EventHandler<EventArgs> MyHandler{get;set;}
    CustomerDelegate HandlerWithCustomDelegate { get; set; }
    event EventHandler<EventArgs> MyEvent;
}
32
eglasius

Un délégué n'est qu'un autre type, vous ne gagnez donc rien en le mettant dans l'interface.

Vous ne devriez pas avoir besoin de créer vos propres délégués. La plupart du temps, vous devriez simplement utiliser EventHandler, Func, Predicate ou Action.

Puis-je vous demander à quoi ressemble votre délégué?

23
Jonathan Allen

Un delegate est un type qui ne peut pas être déclaré dans une interface. Vous souhaiterez peut-être utiliser un événement (le cas échéant) ou déclarer un délégué en dehors de l'interface mais dans le même espace de noms.

Ce lien peut aider - Quand utiliser des délégués au lieu d'interfaces

7
cgreeno

il s'agit d'une décalcomanie de type délégué ...

public delegate returntype MyDelegateType (params)

cela ne peut pas être déclaré dans une interface car c'est une déclaration de type 

cependant, en utilisant la déclaration de type ci-dessus, vous POUVEZ utiliser une instance de délégué 

MyDelegateType MyDelegateInstance ( get; set;)

les instances de délégué sont donc acceptables, mais les déclarations de type de délégué ne le sont pas (dans une interface)

6
Matt

La documentation indique clairement que vous pouvez définir un délégué dans une interface:

Une interface ne contient que les signatures De méthodes, de délégués ou d’événements .

MSDN: interface (référence C #)

Toutefois, dans les remarques de la même page, il est indiqué qu'une interface peut contenir des signatures de méthodes, propriétés, indexeurs et événements.

Si vous essayez de placer un délégué dans une interface, le compilateur indique que "les interfaces ne peuvent pas déclarer les types".

La norme Ecma-334 (8.9 Interfaces) est en accord avec les remarques de cette page et du compilateur.

4
Guffa

Comme d'autres l'ont mentionné, vous ne pouvez définir que des délégués outside de l'interface.

Il n’ya que peu de mal à utiliser des délégués. Personnellement, je pense que Func<int, double> est moins souhaitable que d’utiliser des délégués:

  1. Vous ne pouvez pas nommer les arguments, la signification de l'argument peut donc être ambiguë 
  2. Il est une vieille nouvelle que les événements ne soient pas thread-safe, le code suivant n'est donc pas idéal:

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

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

    Le code le plus sûr est:

    MyFuncEventHandler handler = MyFuncEvent;
    if (handler != null)
    {
        handler(42, 42.42);
    }
    
  3. Vous devez dupliquer la signature de l'événement si vous souhaitez l'enregistrer dans une variable (ou vous pouvez utiliser var, ce que je n'aime pas). Si vous avez beaucoup d'arguments, cela peut devenir très fastidieux (encore une fois, vous pouvez toujours être paresseux et utiliser var).

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

Les délégués vous évitent de dupliquer la signature de la méthode/de l'événement chaque fois que vous souhaitez l'affecter à un type de variable.

1
swooby

Une méthode d'interface peut accepter un délégué en tant que paramètre, pas de problème. (Peut-être que je ne vois pas le problème?) Mais si l'intention est de spécifier un appel sortant dans l'interface, utilisez un événement.

Il y a tellement de petits détails qu'il est beaucoup plus facile de montrer du code au lieu d'essayer de tout décrire en prose. (Désolé, même l'échantillon de code est un peu gonflé ...)

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();
        }
    }
}
0
Paul Williams