Share via


Como declarar e usar um delegado e criar uma instância dele (Guia de Programação em C#)

No C# 1.0 e posterior, os delegados podem ser declarados como mostrado no exemplo a seguir.

// 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 fornece uma maneira mais simples de escrever a declaração anterior, conforme mostrado no exemplo a seguir.

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

No C# 2.0 e posteriores, também é possível usar um método anônimo para declarar e inicializar um delegar, conforme mostrado no exemplo a seguir.

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

No C# 3.0 e posterior, delegados podem também ser declarados e instanciados usando uma expressão lambda, conforme mostrado no exemplo a seguir.

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

Para obter mais informações, consulte Expressões lambda (Guia de Programação em C#).

O exemplo a seguir ilustra a declarar, instanciar e usar um delegado. O BookDB classe encapsula um banco de dados da livraria que mantém um banco de dados de livros. Ele expõe um método, ProcessPaperbackBooks, que localiza o papel de jornal todos os livros no banco de dados e chama um delegado para cada um deles. O delegate tipo usado é denominado ProcessBookDelegate. O Test classe usa essa classe para imprimir os títulos e o preço médio dos livros jornal.

A utilização de delegados promove uma boa separação de funcionalidade entre o banco de dados da livraria e o código do cliente. O código do cliente não tem conhecimento de como os livros são armazenados ou como o código da livraria encontra livros de jornal. O código da livraria não tem conhecimento do qual processamento é realizado no jornal livros após ele encontrá-las.

Exemplo

// 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
*/

Programação robusta

  • Declarar um delegado.

    A instrução a seguir declara um novo tipo de delegado.

    public delegate void ProcessBookDelegate(Book book);
    

    Cada tipo delegado descreve o número e tipos dos argumentos e o tipo de valor de retorno de métodos que ele pode encapsular. Sempre que for necessário um novo conjunto de tipos de argumento ou tipo de valor de retorno, um novo tipo de delegado deve ser declarado.

  • Criar uma instância de um delegado.

    Após ter sido declarado um tipo delegate, um objeto delegado deve ser criado e associado a um método específico. No exemplo anterior, faça isso passando a PrintTitle método para o ProcessPaperbackBooks método como no exemplo a seguir:

    bookDB.ProcessPaperbackBooks(PrintTitle);
    

    Isso cria um novo objeto delegado, associado com o estático método Test.PrintTitle. Da mesma forma, o método non-static AddBookToTotal no objeto totaller é passado como no exemplo a seguir:

    bookDB.ProcessPaperbackBooks(totaller.AddBookToTotal);
    

    Em ambos os casos, um novo objeto delegado é passado para o ProcessPaperbackBooks método.

    Depois de um delegado é criado, o método está associado nunca alterações; delegado são imutáveis.

  • Chamar um delegado.

    Após a criação de um objeto delegado, o objeto delegado normalmente é passado para outro código que entrará em contato com o delegado. Um objeto delegado é chamado usando o nome do objeto delegado, seguido pelos argumentos entre parênteses a serem passados ao delegado. Veja a seguir um exemplo de uma chamada de representante:

    processBook(b);
    

    Um delegado pode ser tanto chamado de forma síncrona, como no exemplo, ou assincronamente usando BeginInvoke e EndInvoke métodos.

Consulte também

Referência

Eventos (Guia de Programação em C#)

Delegados (Guia de Programação em C#)

Conceitos

Guia de Programação em C#