devstory

Tutoriel C# Delegate et Event

  1. Qu'est-ce que Delegate ?
  2. Exemples de delegate
  3. Fonction renvoie une fonction
  4. Méthodes anonymes
  5. Multicasting d'une Delegate
  6. Qu'est - ce que Event ?

1. Qu'est-ce que Delegate ?

En C#, chaque fonction (méthode ou constructeur) a un type de fonction. Voyez la méthode SayHello ci-dessous :
Voyez l'exemple complet :
HelloProgram.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CSharpDelegatesTutorial
{
    class HelloProgram
    { 
        // C'est la méthode qui a un paramètre de du type string et renvoie string
        // Le type de fonction:  (string) -> (string)
        public string SayHello(string name)
        {
            return "Hello " + name;
        }
        
        // C'est la méthode qui a deux paramètres et renvoie string
        // Le type de fonction: (string, string) -> (string)
        public string SayHello(string firstName, string lastName)
        {
            return "Hello " + firstName + " " + lastName;
        }

        // C'est la méthode qui a un paramètre et ne renvoie rien.
        // Le type de fonction: (string) -> ()
        public void Silent(string name)
        {

        }
    }


}
Les deux méthodes suivantes ont le même type de fonction :
C# utilise le mot clés delegate pour définir une entité qui représente la fonction (méthode ou constructeur) ont le même type de fonction.
Syntaxe :
// Syntaxe pour définir une delegate :
delegate <return_type> <delegate_name> <parameter_list>
Exemple :
// Définissez un type représentant le type de fonction
// (string,string) -> (string).
private delegate string MyDelegate(string s1, string s2);

2. Exemples de delegate

MathUtils.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CSharpDelegatesTutorial
{
    class MathUtils
    {

        // (int, int)  -> (int)
        public static int sum(int a, int b)
        {
            return a + b;
        }

        // (int, int)  -> (int)
        public static int minus(int a, int b)
        {
            return a - b;
        }

        // (int, int)  -> (int)
        public static int multiple(int a, int b)
        {
            return a * b;
        }
 

    }

}
.L'exemple ci-dessous définit un delegate IntIntToInt qui représente des fonctions du type (int, int) -> (int).
MyFirstDelegate.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CSharpDelegatesTutorial
{
    class MyFirstDelegate
    {
        // Définissez une delegate pour des fonctions du type
        // (int, int) -> (int)
        delegate int IntIntToInt(int a, int b);



        public static void Main(string[] args)
        {
            // Créez un objet delegate.
            // Transmettez (pass) une fonction au objet. (Même type de fonction avec delegate).
            IntIntToInt iiToInt = new IntIntToInt(MathUtils.sum);

            // Exécutez une delegate.
            // Il appellera la fonction (ou la méthode) qu'elle représente.
            int value = iiToInt(10, 20); // 30

            Console.WriteLine("Value = {0}", value);

            // Attribuez autres valeurs pour  delegate.
            iiToInt = new IntIntToInt(MathUtils.multiple);

            value = iiToInt(10, 20); // 200

            Console.WriteLine("Value = {0}", value);

            Console.Read();

        }


    }


}
Exécutez l'exemple :
Value = 30
Value = 200
Vous pouvez également créer un objet delegate qui représente les fonctions non-statique (pas statique). Voyez l'exemple ci-dessous :
HelloProgramTest.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CSharpDelegatesTutorial
{
    class HelloProgramTest
    {
        // Créez une Delegate
        // Représentez les types de fonctions: (string) -> (string).
        private delegate string StringStringToString(string s);



        public static void Main(string[] args)  
        {

            // Créez un object HelloProgram.
            HelloProgram program = new HelloProgram();

            // Créez un object Delegate représente la fonction sayHello.
            StringStringToString ssToS = new StringStringToString(program.SayHello);


            // Test 
            string greeting = ssToS("Tom");

            Console.WriteLine(greeting);

            Console.Read();
        }

    }


}

3. Fonction renvoie une fonction

En C#, avec Delegate, vous pouvez créer une fonction qui renvoie une fonction (Le fait qu'une fonction renvoie une Delegate).
TaxFormulas.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CSharpDelegatesTutorial
{
    class TaxFormulas
    {
        // Une Delegate qui représente le typede focntion : (float) -> (float).
        public delegate float TaxFormula(float salary);

        // La formule de calcul de l'impôt au État- Unis (10% du salaire)..
        public static float UsaFormula(float salary)
        {
            return 10 * salary / 100;
        }

        // La formule de calcul de l'impôt du Vietnam (5% du salaire).
        public static float VietnamFormula(float salary)
        {
            return 5 * salary / 100;
        }

        // La formule de calcul de l'impôt par défaut (7% du salaire).
        public static float DefaultFormula(float salary)
        {
            return 7 * salary / 100;
        }

        // Renvoie une fonction pour calculer l'impôt,
        // sur la base du code national (VN, USA, ...)
        public static TaxFormula GetSalaryFormula(string countryCode)
        {
            if (countryCode == "VN")
            {
                return TaxFormulas.VietnamFormula;
            }
            else if (countryCode == "USA")
            {
                return TaxFormulas.UsaFormula;
            }
            return TaxFormulas.DefaultFormula;
        }

    }

}
TaxFormulaTest.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CSharpDelegatesTutorial
{
    class TaxFormulaTest
    {


        public static void Main(string[] args)
        {
            float salary = 1000f;

            // La formule pour calculer l'impôt au Vietnam.
            TaxFormulas.TaxFormula formula = TaxFormulas.GetSalaryFormula("VN");

            float tax = formula(salary);

            Console.WriteLine("Tax in Vietnam = {0}", tax);

            // ​​​​​​​
            // La formule de calcul de l'impôt au Canada.
            formula = TaxFormulas.GetSalaryFormula("CA");

            tax = formula(salary);

            Console.WriteLine("Tax in Canada = {0}", tax);

            Console.Read();
        }
    }

}
Exécutez l'exemple :
Tax in Vietname = 50
Tax in Canada = 70

4. Méthodes anonymes

Basé sur Delegate, vous pouvez créer une méthode anonyme. Elle est une méthode qui n'a pas de nom mais elle a du corps (body) de la méthode, elle est un bloc de 0 ou plusieurs paramètres ou le type de retour.
AnonymousMethod.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CSharpDelegatesTutorial
{
    class AnonymousMethod
    {
        // Une Delegate qui représente le type de fonction : (float) -> (float).
        // Calcul de l'impôt basé sur le salaire.
        public delegate float TaxFormula(float salary);


        public static TaxFormula GetTaxFormula(string countryCode)
        {
            if ("USA" == countryCode)
            {
                TaxFormula usaFormula = delegate(float salary)
                {
                    return 10 * salary / 100;
                };
                return usaFormula;
            }
            else if ("VN" == countryCode)
            {
                TaxFormula vnFormula = delegate(float salary)
                {
                    return 5 * salary / 100;
                };
                return vnFormula;
            }
            return delegate(float salary)
            {
                return 7 * salary / 100;
            };
        }


        public static void Main(string[] args)
        {
            string countryCode = "VN";
            float salary = 1000;

            TaxFormula formula = GetTaxFormula(countryCode);

            float tax = formula(salary);

            Console.WriteLine("countryCode = {0}, salary = {1} -> tax = {2}"
                                    , countryCode, salary, tax);

            Console.Read();
        }
    }

}
Exécutez l'exemple :

countryCode = VN, salary = 1000 -> tax = 50

5. Multicasting d'une Delegate

C# vous permet d'ajouter (+) deux objets Delegates ensemble pour former un nouvel objet Delegate. Il est à noter que les objets Delegates peuvent être avoir de même type de fonction et la fonction n'a pas de type de retour. Lorsqu'un nouvel objet Delegate est appelé, tous les Delegates seront également exécutés. Ce concept est appelé Multicast de Delegate.
Greetings.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CSharpDelegatesTutorial
{
    class Greetings
    {
        // Type de fonction : (String) -> ()
        public static void Hello(String name)
        {
            Console.WriteLine("Hello " + name);
        }

        // Type de fonction : (String) -> ()
        public static void Bye(string name)
        {
            Console.WriteLine("Bye " + name);
        }

        // Type de fonction : (String) -> ()
        public static void Hi(string name)
        {
            Console.WriteLine("Hi " + name);
        }
    }

}
MulticastingTest.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CSharpDelegatesTutorial
{
    class MulticastingTest
    {
        // Déclarez un Delegate
        public delegate void Greeting(string name);


        public static void Main(string[] args)
        {
            // Créez des objets Delegate.
            Greeting hello = new Greeting(Greetings.Hello);
            Greeting bye = new Greeting(Greetings.Bye);
            Greeting hi = new Greeting(Greetings.Hi);
            
            // Créez un Delegate (la somme de deux Delegates).
            Greeting greeting = hello + bye;
           
            // Vous pouvez également utiliser l'opérateur + =.
            greeting += hi;

            // Exécutez greeting.
            greeting("Tom");

            Console.Read();


        }
    }

}
Exécutez l'exemple :
Hello Tom
Bye Tom
Hi Tom

6. Qu'est - ce que Event ?

En C#, Event est un objet spécial de Delegate qui contient des méthodes exécutées simultanément lorsque l'événement a eu lieu. Vous pouvez ajouter les méthodes qui seront exécutées sur l'objet Event de l'objet émettant l'événement .
Example:
La classe Button simule un bouton qui définit un Event (événement) afin d'informer qu'il vient d'être cliqué. Lorsque le bouton est cliqué, Event sera exécuté. Vous devez ajouter les méthodes nécessaires de l'exécution de Event depuis l'extérieur.
Button.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CSharpEventsTutorial
{
    class Button
    {

        private string label;

        public delegate void ClickHander(Button source, int x, int y);

        // Définissez un événement, il n'a pas été attribué de valeur.
        // Sa valeur est attribuée de l'extérieur.
        public event ClickHander OnButtonClick;

        public Button(string label)
        {
            this.label = label;
        }

        // Simulez le Bouton est cliqué(Click).
        // Déterminez la position x, y que l'utilisateur clique.
        public void Clicked()
        {
            Random random = new Random();

            // Un nombre aléatoire entre 1 -> 100
            int x = random.Next(1, 100);

            // Un nombre aléatoire entre  1 -> 20
            int y = random.Next(1, 20);


            if (OnButtonClick != null)
            {
                // ​​​​​​​
                // Appelez les gestionnaires d'événement.
                OnButtonClick(this, x, y);
            }
            
        }
    }


}
La classe MyApplication simule une application de a deux boutons, "Open File" et "Save File".

Vous devez écrire la méthode pour faire quelque chose lorsque l'utilisateur clique sur "Open File" et ajouter cette méthode pour l'événement OnButtonClick du bouton openButton.

Vous devez écrire la méthode pour faire quelque chose lorsque l'utilisateur clique sur "Save File" et ajouter cette méthode à l'événement OnButtonClick du bouton saveButton.
MyApplication.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CSharpEventsTutorial
{
    class MyApplication
    {
        private Button openButton;
        private Button saveButton;
        private string fileName;

        // Simulez d'une application avec les Boutons.
        public MyApplication()
        {
            // Ajoutez un bouton à l'interface.
            this.openButton = new Button("Open File");

            // Ajoutez un bouton à l'interface.
            this.saveButton = new Button("Save File");

            // Ajoutez une méthode à l'événement du bouton 'Open Button'.
            // (Caractéristiques Multicasting de Delegate)
            this.openButton.OnButtonClick += this.OpenButtonClicked;

            // Ajoutez la méthode à l'événement du bouton 'Save Button'.
            // (Caractéristiques Multicasting de Delegate)
            this.saveButton.OnButtonClick += this.SaveButtonClicked;
        }

        private void OpenButtonClicked(Button source, int x, int y)
        {
            // Simulez ouvre une fenêtre pour sélectionner le fichier à ouvrir.
            Console.WriteLine("Open Dialog to Select a file");
            // 
            this.fileName = "File" + x + "_" + y+".txt";
            Console.WriteLine("Openning file: "+ this.fileName);
        }

        private void SaveButtonClicked(Button source, int x, int y)
        {
            if(this.fileName== null)  {
                Console.WriteLine("No file to save!");
                return;
            }
            // Save File
            Console.WriteLine("Saved file: " + this.fileName);
        }
 

        public static void Main(string[] args)
        {

            // Ouvrez l'application
            MyApplication myApp = new MyApplication();

            Console.WriteLine("User Click on Open Button ....");

            // Cliquez sur le bouton openButton 
            myApp.openButton.Clicked();

            Console.WriteLine("\n\n");
            Console.WriteLine("User Click on Save Button ....");

            // Cliquez sur le bouton saveButton
            myApp.saveButton.Clicked();


            Console.Read();
            
        }
    }

}
Exécutez l'exemple :
User Click on Open Button ....
Open Dialog to Select a file
Openning file: File75_4.txt

User Click on Save Button ....
Saved file: File75_4.txt