web-dev-qa-db-fra.com

Délégués vs interfaces en C #

Je voudrais poser cette question tant que j'essaie actuellement de creuser dans l'utilisation et le but des délégués, bien qu'elle ait probablement été posée dans des formulations similaires.

Je sais que les délégués servent de pointeurs de fonction utilisés en C++. Le fait est que si en C # ils servent principalement d'alternative aux interfaces et au polymorphisme. Étant donné que je peux créer des sous-classes d'une classe spécifique et leur fournir les méthodes appropriées à chacune, que proposent les délégués en plus? Y a-t-il des cas qui stipulent leur utilisation ou la simple maintenabilité du code est-elle améliorée lorsque les délégués l'utilisent? Recommanderiez-vous leur large déploiement sur les interfaces?

Je parle uniquement des délégués et je veux distinguer leur rôle de celui des événements.

50
arjacsoh

Oui, les délégués sont à bien des égards comme des interfaces à méthode unique. Pourtant:

  • Il y a un support intégré dans le CLR pour eux
  • Il y a un support dans le cadre pour eux, y compris les capacités multi-cast et l'invocation asynchrone
  • Il existe un support supplémentaire du langage C #/VB sous la forme de conversions de groupes de méthodes, d'expressions lambda, de méthodes anonymes
  • Ils sont mandatés pour les événements (c'est-à-dire que les événements et les délégués sont une sorte de paire correspondante)
  • Ils signifient que vous ne pas devez implémenter une interface dans une classe distincte pour chaque instance de délégué que vous souhaitez créer.

Le dernier point est le plus important - considérez une expression LINQ de:

var query = collection.Where(x => x > 5)
                      .Select(x => x * x);

Imaginez maintenant si vous souhaitez exprimer la logique de x > 5 et x * x vous deviez écrire une classe distincte pour chaque expression, et implémenter une interface: la quantité de code cru vs utile serait ridicule. Bien sûr, le langage pourrait a été conçu pour permettre les conversions d'expressions lambda en implémentations d'interface via des classes distinctes, mais vous perdriez encore l'avantage de pouvoir simplement écrire une méthode distincte et créer un déléguer avec cela comme cible. Vous perdriez également les capacités de multidiffusion.

Comme exercice de réflexion similaire, envisagez de mettre en boucle des instructions telles que while et for. Avons-nous vraiment besoin eux quand nous avons goto? Nan. Mais la vie est bien meilleure avec eux. Il en va de même pour les délégués - et en effet les propriétés, les événements, etc. Ils rendent tous le développement plus simple.

71
Jon Skeet

La plus grande différence pratique est que vous pouvez fournir différentes instances de délégué pour le même délégué de la même classe, alors que vous ne pouvez pas le faire avec des interfaces.

void delegate XYZ(int p);

interface IXyz {
    void doit(int p);
}

class One {
    // All four methods below can be used to implement the XYZ delegate
    void XYZ1(int p) {...}
    void XYZ2(int p) {...}
    void XYZ3(int p) {...}
    void XYZ4(int p) {...}
}

class Two : IXyz {
    public void doit(int p) {
        // Only this method could be used to call an implementation through an interface
    }
}
28
dasblinkenlight

De Quand utiliser les délégués au lieu des interfaces (MSDN) :

Les délégués et les interfaces permettent à un concepteur de classe de séparer les déclarations de type et l'implémentation. Une interface donnée peut être héritée et implémentée par n'importe quelle classe ou structure. Un délégué peut être créé pour une méthode sur n'importe quelle classe, tant que la méthode correspond à la signature de méthode du délégué. Une référence d'interface ou un délégué peut être utilisé par un objet qui n'a aucune connaissance de la classe qui implémente l'interface ou la méthode déléguée. Compte tenu de ces similitudes, quand un concepteur de classe doit-il utiliser un délégué et quand doit-il utiliser une interface?

Utilisez un délégué dans les circonstances suivantes:

  • Un modèle de conception de concours complet est utilisé.
  • Il est souhaitable d'encapsuler une méthode statique.
  • L'appelant n'a pas besoin d'accéder à d'autres propriétés, méthodes ou interfaces sur l'objet implémentant la méthode.
  • Une composition facile est souhaitée.
  • Une classe peut nécessiter plusieurs implémentations de la méthode.

Utilisez une interface dans les circonstances suivantes:

  • Il existe un groupe de méthodes connexes qui peuvent être appelées.
  • Une classe n'a besoin que d'une implémentation de la méthode.
  • La classe utilisant l'interface voudra convertir cette interface en d'autres types d'interface ou de classe.
  • La méthode implémentée est liée au type ou à l'identité de la classe: par exemple, les méthodes de comparaison.

IComparable ou la version générique, IComparable (Of T) est un bon exemple d'utilisation d'une interface à méthode unique au lieu d'un délégué. IComparable déclare la méthode CompareTo, qui retourne un entier qui spécifie une relation inférieure, égale ou supérieure à entre deux objets du même type. IComparable peut être utilisé comme base d'un algorithme de tri. Bien que l'utilisation d'une méthode de comparaison des délégués comme base d'un algorithme de tri soit valide, elle n'est pas idéale. Étant donné que la capacité de comparaison appartient à la classe et que l'algorithme de comparaison ne change pas au moment de l'exécution, une interface à méthode unique est idéale.

De Délégué Vs Interfaces en C # :

Les délégués et les interfaces sont deux concepts distincts en C # mais ils partagent un point commun. Les délégués et les interfaces incluent uniquement la déclaration. L'implémentation est effectuée par un objet de programmation différent.

16
Lion

Les délégués et les interfaces sont deux concepts distincts en C #.

Les interfaces permettent d'étendre la fonctionnalité de certains objets, c'est un contrat entre l'interface et l'objet qui l'implémente, alors que les délégués ne sont que des rappels sécurisés, ils sont une sorte de pointeurs de fonction.

4
aleroot

Les seuls avantages réels des délégués sur les interfaces sont

  1. Les délégués pouvaient traiter différents types d'arguments avant même les génériques pris en charge par .Net.
  2. Une classe peut créer des délégués exposant plusieurs méthodes différentes partageant la même signature; le remplacement des délégués par des interfaces signifierait que chaque classe pourrait exposer une méthode qui implémenterait chaque interface de style délégué sans créer de classes auxiliaires, mais aurait besoin d'une classe auxiliaire pour chaque implémentation supplémentaire.

Lorsque .net ne prenait pas en charge les génériques, les délégués en faisaient partie intégrante, car déclarer des interfaces distinctes non génériques pour chaque signature de fonction que l'on voudrait passer aurait été impossible. Si .net avait pris en charge les génériques depuis le début, les délégués n'auraient pas été nécessaires, sauf pour certains scénarios impliquant Reflection, et même là, il aurait peut-être été plus utile d'avoir le type Action<T,U> être une implémentation de IAction<T,U> (donc ce code qui a simplement besoin de quelque chose qu'il peut Invoke utiliserait l'interface). Une approche basée sur l'interface aurait nécessité la création de classes à méthode unique dans les cas où les classes doivent créer des délégués exposant plusieurs méthodes, mais aurait éliminé la nécessité de créer des instances de délégué distinctes dans les nombreux cas courants où le nombre de méthodes d'un la signature à exposer en est précisément une.

Par ailleurs, le remplacement des délégués par des interfaces n'empêcherait en aucun cas la création d'une méthode Combine à usage général. En effet, la covariance d'interface pourrait rendre une telle méthode plus efficace que la Delegate.Combine à bien des égards. Implémentation d'une méthode analogue à Delegate.Remove serait au mieux maladroit et ennuyeux, mais je ne pense à aucune situation autre que la gestion des abonnements aux événements qui nécessiterait l'utilisation de Delegate.Remove, et l'abonnement aux événements pourrait de toute façon être mieux géré en utilisant d'autres approches.

1
supercat