Partager via


Comment : déclarer, instancier et utiliser un délégué (Guide de programmation C#)

Dans C# 1.0 et dans les versions ultérieures, les délégués peuvent être déclarés comme indiqué dans l'exemple suivant.

// Declare a delegate. 
delegate void Del(string str);

// Declare a method with the same signature as the delegate. 
static void Notify(string name)
{
    Console.WriteLine("Notification received for: {0}", name);
}
// Create an instance of the delegate.
Del del1 = new Del(Notify);

C# 2.0 offre un moyen plus simple d'écrire la déclaration précédente, comme indiqué dans l'exemple suivant.

// C# 2.0 provides a simpler way to declare an instance of Del.
Del del2 = Notify;

Dans C# 2.0 et les versions ultérieures, il est également possible d'utiliser une méthode anonyme pour déclarer et initialiser un délégué 900fyy8e(v=vs.120).md, comme indiqué dans l'exemple suivant.

// Instantiate Del by using an anonymous method.
Del del3 = delegate(string name)
    { Console.WriteLine("Notification received for: {0}", name); };

Dans C# 3.0 et les versions ultérieures, les délégués peuvent également être déclarés et instanciés à l'aide d'une expression lambda, comme indiqué dans l'exemple suivant.

// Instantiate Del by using a lambda expression.
Del del4 = name =>  { Console.WriteLine("Notification received for: {0}", name); };

Pour plus d'informations, consultez Expressions lambda (Guide de programmation C#).

L'exemple suivant illustre la déclaration, l'instanciation et l'utilisation d'un délégué. La classe BookDB encapsule une base de données de librairie qui gère une base de données de livres. Elle expose une méthode ProcessPaperbackBooks, qui recherche tous les livres de poche dans la base de données et appelle un délégué pour chacun d'entre eux. Le type delegate qui est utilisé est nommé ProcessBookDelegate. La classe Test utilise cette classe pour imprimer les titres et le prix moyen des livres de poche.

L'utilisation de délégués favorise une bonne séparation des fonctionnalités entre la base de données de la librairie et le code client. Le code client ignore complètement comment les livres sont stockés et comment le code libraire recherche les livres de poche. Inversement, le code libraire ignore quel traitement est effectué sur les livres de poche lorsqu'il les a trouvés.

Exemple

// A set of classes for handling a bookstore: 
namespace Bookstore
{
    using System.Collections;

    // Describes a book in the book list: 
    public struct Book
    {
        public string Title;        // Title of the book. 
        public string Author;       // Author of the book. 
        public decimal Price;       // Price of the book. 
        public bool Paperback;      // Is it paperback? 

        public Book(string title, string author, decimal price, bool paperBack)
        {
            Title = title;
            Author = author;
            Price = price;
            Paperback = paperBack;
        }
    }

    // Declare a delegate type for processing a book: 
    public delegate void ProcessBookDelegate(Book book);

    // Maintains a book database. 
    public class BookDB
    {
        // List of all books in the database:
        ArrayList list = new ArrayList();

        // Add a book to the database: 
        public void AddBook(string title, string author, decimal price, bool paperBack)
        {
            list.Add(new Book(title, author, price, paperBack));
        }

        // Call a passed-in delegate on each paperback book to process it:  
        public void ProcessPaperbackBooks(ProcessBookDelegate processBook)
        {
            foreach (Book b in list)
            {
                if (b.Paperback)
                    // Calling the delegate:
                    processBook(b);
            }
        }
    }
}


// Using the Bookstore classes: 
namespace BookTestClient
{
    using Bookstore;

    // Class to total and average prices of books: 
    class PriceTotaller
    {
        int countBooks = 0;
        decimal priceBooks = 0.0m;

        internal void AddBookToTotal(Book book)
        {
            countBooks += 1;
            priceBooks += book.Price;
        }

        internal decimal AveragePrice()
        {
            return priceBooks / countBooks;
        }
    }

    // Class to test the book database: 
    class TestBookDB
    {
        // Print the title of the book. 
        static void PrintTitle(Book b)
        {
            System.Console.WriteLine("   {0}", b.Title);
        }

        // Execution starts here. 
        static void Main()
        {
            BookDB bookDB = new BookDB();

            // Initialize the database with some books:
            AddBooks(bookDB);

            // Print all the titles of paperbacks:
            System.Console.WriteLine("Paperback Book Titles:");

            // Create a new delegate object associated with the static  
            // method Test.PrintTitle:
            bookDB.ProcessPaperbackBooks(PrintTitle);

            // Get the average price of a paperback by using 
            // a PriceTotaller object:
            PriceTotaller totaller = new PriceTotaller();

            // Create a new delegate object associated with the nonstatic  
            // method AddBookToTotal on the object totaller:
            bookDB.ProcessPaperbackBooks(totaller.AddBookToTotal);

            System.Console.WriteLine("Average Paperback Book Price: ${0:#.##}",
                    totaller.AveragePrice());
        }

        // Initialize the book database with some test books: 
        static void AddBooks(BookDB bookDB)
        {
            bookDB.AddBook("The C Programming Language", "Brian W. Kernighan and Dennis M. Ritchie", 19.95m, true);
            bookDB.AddBook("The Unicode Standard 2.0", "The Unicode Consortium", 39.95m, true);
            bookDB.AddBook("The MS-DOS Encyclopedia", "Ray Duncan", 129.95m, false);
            bookDB.AddBook("Dogbert's Clues for the Clueless", "Scott Adams", 12.00m, true);
        }
    }
}
/* Output:
Paperback Book Titles:
   The C Programming Language
   The Unicode Standard 2.0
   Dogbert's Clues for the Clueless
Average Paperback Book Price: $23.97
*/

Programmation fiable

  • Déclaration d'un délégué.

    L'instruction suivante déclare un nouveau type délégué.

    public delegate void ProcessBookDelegate(Book book);
    

    Chaque type délégué décrit le nombre et les types des arguments, ainsi que le type de la valeur de retour des méthodes qu'il peut encapsuler. Chaque fois qu'un nouvel ensemble de types d'argument ou qu'un nouveau type de valeur de retour est requis, un nouveau type délégué doit être déclaré.

  • Instanciation d'un délégué.

    Après qu'un type délégué a été déclaré, un objet délégué doit être créé et associé à une méthode particulière. Dans l'exemple précédent, pour ce faire, vous passez la méthode PrintTitle à la méthode ProcessPaperbackBooks comme dans l'exemple suivant :

    bookDB.ProcessPaperbackBooks(PrintTitle);
    

    Cela crée un objet de délégué associé à la méthode statique Test.PrintTitle. De la même manière, la méthode non statique AddBookToTotal sur l'objet totaller est passée comme dans l'exemple suivant :

    bookDB.ProcessPaperbackBooks(totaller.AddBookToTotal);
    

    Dans les deux cas, un nouvel objet délégué est passé à la méthode ProcessPaperbackBooks.

    Après qu'un délégué est créé, la méthode à laquelle il est associé ne change jamais ; les objets délégués sont immuables.

  • Appel d'un délégué.

    Après qu'un objet délégué est créé, il est normalement transmis à un autre code qui appellera le délégué. Vous pouvez appeler un objet délégué en utilisant son nom, suivi, entre parenthèses, des arguments qui doivent être transmis au délégué. Un exemple d'appel de délégué est fourni ci-dessous :

    processBook(b);
    

    Un délégué peut faire l'objet d'un appel synchrone, comme dans cet exemple, ou d'un appel asynchrone à l'aide des méthodes BeginInvoke et EndInvoke.

Voir aussi

Référence

Événements (Guide de programmation C#)

Délégués (guide de programmation C#)

Concepts

Guide de programmation C#