DotnetDojo

Développer des applications modernes avec les technologies Microsoft et Open source

  • Blog
  • Vidéos
  • Formations
  • Outils

Bien comprendre les delegates en C# (csharp)

Cet article traite d’un sujet important concernant les types délégués en C# (csharp).
Il fera sans doute partie d’une série d’article sur les bases de CSharp.

Nous allons donc voir ce que sont les delegates et pourquoi ils sont très importants dans le développement d’application .NET.

Qu’est-ce qu’un type delegate ?

En fait, un type delegate est un concept très simple : c’est un type qui permet de référencer une méthode d’une classe.
Grâce aux delegates, vous pouvez transmettre une méthode comme paramètre (c’est un peu l’équivalent des pointeurs de fonction en C / C++ par exemple).

Un type délégué (delegate en anglais) est toujours associé à la signature d’une méthode.
Seules les méthodes ayant la même signature pourront être utilisées avec ce délégué.

delegate est aussi un mot clé du langage C# (csharp) qui permet de déclarer un delegate.

Pour déclarer un delegate en CSharp, voici ce qu’il faut faire :

  • dans votre classe, vous utilisez le mot clé delegate suivi de la signature de la méthode associée,
  • le nom de la méthode indiquée dans la signature sera le nom de votre delegate,
  • vous pouvez éventuellement ajouter un indicateur de visibilité au début (private, public ou protected par exemple).

Voici un exemple de code qui permet de déclarer un delegate en C# :

public class MaClasse
{
    public delegate int Calculer(List<int> elements);
}

Dans cet exemple, je déclare un delegate pour une méthode qui prend en argument une liste d’int et qui retourne un int.
Toutes les méthodes correspondantes à cette signature pourront être utilisée avec ce delegate.

Comment utiliser un delegate ?

Après avoir déclaré un type délégué, il faut désormais l’utiliser votre delegate dans votre code CSharp.

Un type delegate peut être utilisé comme n’importe quel type en C# : dans les méthodes (arguments en entrée, paramètre de retour) ou dans les classes (propriété ou membre).

Voici un exemple d’utilisation de type délégué en C# (suite de l’exemple précédent) :

int MaMethodeDeCalcul(List<int> elements)
{
    return elements.Count;
}

void Main()
{
    MaClasse.Calculer delegateCalculer = new MaClasse.Calculer(MaMethodeDeCalcul);
    MaClasse instance = new MaClasse();

    // ici, j’appelle la méthode Traiter de MaClasse
    // en passant le délégué comme argument.
    instance.Traiter(delegateCalculer);

    // vous auriez aussi pu écrire ceci :
    // instance.Traiter(new MaClasse.Calculer(MaMethodeDeCalcul));
    // ou même ceci (depuis les dernières versions de C#) :
    // instance.Traiter(MaMethodeDeCalcul);
}

Ok, jusque là, vous allez me dire : bon, mais ça sert à quoi un delegate ?

L’utilisation la plus courante des types délégués

Les types délégués en C# permettent de passer des méthodes comme argument lors des appels.
Il est donc possible de créer des comportements différents pour un même code.

En effet, les types délégués sont des points d’extension de votre code.
Il sera possible de changer le comportement d’un morceau de code simplement en passant un autre delegate.

Voici un exemple très simple :

  • Vous avez une classe qui effectue des calculs sur une série de nombres,
  • Une méthode « Calculer » prend en argument une liste d’entiers et deux delegates : AvantTraitementDelegate et ApresTraitementDelegate,
  • Ces deux delegates ont pour fonction de pouvoir filtrer ou modifier une série d’éléments avant ou après un traitement,
  • La méthode Calculer pourra être appellée plusieurs fois dans votre application avec des références vers différentes méthodes.

Pour mieux comprendre, je vous propose un exemple qui montre deux appels différents :


public MaClasseDeTraitement
{
    public delegate void AvantTraitementDelegate(List<int> elements);
    public delegate List<int> ApresTraitementDelegate(List<int> elements);

    // Méthode de calcul simple (inverser la liste)
    public List<int> Calculer(List<int> elements,
        AvantTraitementDelegate avant, ApresTraitementDelegate apres)
    {
        List<int> copie = new List<int>(elements);

        // appel du delegate si défini
        if (avant != null) avant(copie);

        copie.Reverse();

        // appel du delegate si défini
        if (apres != null) copie = apres(copie);

        return copie;
    }
}

// Cette méthode ajoute un à chaque élément
void AjouterUn(List<int> elements)
{
    for (int i = 0; i < elements.Count; i++)
        elements[i] = elements[i] + 1;
}

// Cette méthode supprime les 0 de la liste
List<int> SupprimerZero(List<int> elements)
{
  elements.Remove(0);
  return elements;
}

void Main()
{
 MaClasseDeTraitement traitement = new MaClasseDeTraitement();
 List<int> elements = new List<int>();
 // TODO: remplir la liste ici

 // Ici, j'appelle Calculer en passant les elements
 // mais sans delegate
 List<int> resultat1 = traitement.Calculer(elements, null, null);

 // Cette fois-ci, on effectue l'appel mais
 // en passant deux delegates :
 // Le premier effectue un pré-traitement (ajouter un à chaque élément),
 // Le second supprimer les 0 de la liste.
 List<int> resultat2 = traitement.Calculer(elements, AjouterUn, SupprimerZero);
}

Comme vous le voyez, il est possible de faire des opérations différentes en fonction des méthodes passées en paramètre.

  • Dans le premier cas, on appelle Calculer sans méthode de traitement.
  • Dans le second cas, on appelle Calculer avec les deux méthodes de traitement, ce qui va donc produire un résultat complètement différent.

Pourquoi les delegates sont-ils si importants ?

Les types délégués sont importants en C# pour deux raisons essentiellement :

  • Tout d’abord, car ils sont utilisés partout dans le framework Dotnet. Il est donc très important de bien comprendre ce concept pour utiliser le framework .NET correctement.
  • Les types délégués sont utilisés pour mettre en place le principe de l’Ouvert-fermé (j’en parle dans l’article Concevoir des applications SOLID avec OCP).

Comment aller plus loin ?

Si vous souhaitez utiliser le framework .NET de manière optimale, je vous conseille fortement de pratiquer et d’essayer d’utiliser puis de créer vos propres delegates.

C’est pour ça que je vous ai préparé, en bonus de cet article, une fiche méthode qui résume l’essentiel et qui vous propose des exercices pour aller plus loin dans la pratique.

Télécharger le bonus complémentaire

Besoin de résultats rapides ?

Découvrez les formations vidéos que je propose :

  

 

Formations en présentiel (dans toute la France)

Découvrez également les formations C# et .NET que je donne en présentiel (en France)

Comments

  1. Morgan says

    19 novembre 2013 at 11 h 01 min

    Enfin un article qui me permet de comprendre facilement le comportement des delegates grâce à des exemples simples
    Merci beaucoup

    • Pascal Lacroix says

      19 novembre 2013 at 14 h 45 min

      Merci Morgan, je vous invite à suivre le prochain sur les events.

  2. Jean-Baptiste BINARD says

    19 novembre 2013 at 12 h 49 min

    Classique mais c’est impressionant le nombre de personne faisant du c# et ne connaissant pas (ou alors ne les utilisant jamais) les délégates ! Un rappel ne fait pas de mal.

    • Pascal Lacroix says

      19 novembre 2013 at 14 h 46 min

      Effectivement les delegates sont importants et puissants en C#. C’est presque la base du langage et du framework .NET.

  3. Jonathan says

    28 novembre 2013 at 16 h 16 min

    Bonjour,
    Tout d’abord merci, c’est vraiment une notion que je trouvais super abstraite et que j’apréhende mieux maintenant. Sinon, dans le code que tu donnes, je crois que la méthode AjouterUn est en double, la deuxième ne devrait pas s’appeler SupprimerZero?

    Sinon super travail, j’aime aussi beaucoup l’idée de proposer des katas pour s’améliorer.

    Bonne continuation,

    Jonathan

    • Pascal Lacroix says

      29 novembre 2013 at 22 h 24 min

      Bonjour Jonathan,

      Merci de ton retour. Je viens de corriger l’erreur.

  4. mellouze says

    4 mai 2014 at 15 h 55 min

    Hello, Il y a un petit souci au niveau du code, la méthode supprimer zéro n’as pas la meme signature que ton delegate ApresTraitementDelegate. il y a donc un petit souci avec ton exemple.

    • Pascal Lacroix says

      11 juin 2014 at 14 h 14 min

      Merci, effectivement, il faut retourner « List

Le guide gratuit pour écrire du meilleur code dès aujourd'hui.
Entrez votre email pour le recevoir.

A propos de DotnetDojo

Pascal Lacroix

Je m’appelle Pascal et je suis passionné par le développement logiciel, l’efficacité et l’entrepreneuriat. Sur DotnetDojo, je vous propose des méthodes pour apprendre à développer des applications modernes avec les technologies Microsoft et Open Source.

En savoir plus

  • Populaire
  • Récent

Liens complémentaires

  • A propos de DotnetDojo
  • 18 principes pour professionnaliser le développement logiciel
  • Boite à outils du développeur
  • Tous les articles
  • Liste des formations
  • Contact

Copyright 2019 Jupiteo · Mentions légales · Contact · CGV · Offres d'emploi .NET · Formations Dotnet

Nous utilisons des cookies pour vous garantir la meilleure expérience sur notre site. Si vous continuez à utiliser ce dernier, nous considérerons que vous acceptez l'utilisation des cookies.Ok