Jak zadeklarować, utworzyć wystąpienie i użyć delegata (Przewodnik programowania w języku C#)
Delegatów można zadeklarować przy użyciu dowolnej z następujących metod:
- Zadeklaruj typ delegata i zadeklaruj metodę z pasującym podpisem:
// Declare a delegate.
delegate void NotifyCallback(string str);
// Declare a method with the same signature as the delegate.
static void Notify(string name)
{
Console.WriteLine($"Notification received for: {name}");
}
// Create an instance of the delegate.
NotifyCallback del1 = new NotifyCallback(Notify);
- Przypisz grupę metod do typu delegata:
// C# 2.0 provides a simpler way to declare an instance of NotifyCallback.
NotifyCallback del2 = Notify;
- Zadeklaruj metodę anonimową:
// Instantiate NotifyCallback by using an anonymous method.
NotifyCallback del3 = delegate(string name)
{ Console.WriteLine($"Notification received for: {name}"); };
- Użyj wyrażenia lambda:
// Instantiate NotifyCallback by using a lambda expression.
NotifyCallback del4 = name => { Console.WriteLine($"Notification received for: {name}"); };
Aby uzyskać więcej informacji, zobacz Wyrażenia lambda.
Poniższy przykład ilustruje deklarowanie, tworzenie wystąpień i używanie delegata. Klasa BookDB
hermetyzuje bazę danych księgarni, która utrzymuje bazę danych książek. Uwidacznia metodę , ProcessPaperbackBooks
która znajduje wszystkie książki papierowe w bazie danych i wywołuje delegata dla każdego z nich. Używany delegate
typ nosi nazwę ProcessBookCallback
. Klasa Test
używa tej klasy do drukowania tytułów i średniej ceny książek papierowych.
Użycie delegatów promuje dobre rozdzielenie funkcjonalności między bazą danych księgarni a kodem klienta. Kod klienta nie ma wiedzy na temat sposobu przechowywania książek ani sposobu, w jaki kod księgarni znajduje książki zwrotne. Kod księgarni nie ma wiedzy na temat tego, jakie przetwarzanie jest wykonywane na książkach papierowych po ich znalezieniu.
Przykład
// 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 ProcessBookCallback(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(ProcessBookCallback 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 Test
{
// Print the title of the book.
static void PrintTitle(Book b)
{
Console.WriteLine($" {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:
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);
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
*/
Niezawodne programowanie
Deklarowanie delegata.
Poniższa instrukcja deklaruje nowy typ delegata.
public delegate void ProcessBookCallback(Book book);
Każdy typ delegata opisuje liczbę i typy argumentów oraz typ zwracanej wartości metod, które może hermetyzować. Za każdym razem, gdy jest wymagany nowy zestaw typów argumentów lub zwracany typ wartości, należy zadeklarować nowy typ delegata.
Utworzenie wystąpienia delegata.
Po zadeklarowaniu typu delegata należy utworzyć obiekt delegata i skojarzyć go z określoną metodą. W poprzednim przykładzie należy to zrobić, przekazując
PrintTitle
metodę doProcessPaperbackBooks
metody, jak w poniższym przykładzie:bookDB.ProcessPaperbackBooks(PrintTitle);
Spowoduje to utworzenie nowego obiektu delegata skojarzonego z metodą
Test.PrintTitle
statyczną . Podobnie metodaAddBookToTotal
niestatyczna obiektutotaller
jest przekazywana tak jak w poniższym przykładzie:bookDB.ProcessPaperbackBooks(totaller.AddBookToTotal);
W obu przypadkach nowy obiekt delegata jest przekazywany do
ProcessPaperbackBooks
metody .Po utworzeniu delegata metoda jest skojarzona z nigdy nie zmienia się; obiekty delegowane są niezmienne.
Wywoływanie delegata.
Po utworzeniu obiektu delegata obiekt delegata jest zwykle przekazywany do innego kodu, który będzie wywoływać delegata. Obiekt delegata jest wywoływany przy użyciu nazwy obiektu delegata, a następnie argumentów nawiasów, które mają zostać przekazane do delegata. Oto przykład wywołania delegata:
processBook(b);
Delegat może być wywoływany synchronicznie, tak jak w tym przykładzie, lub asynchronicznie przy użyciu metod
BeginInvoke
iEndInvoke
.