Så här deklarerar, instansierar och använder du en delegat (C#-programmeringsguide)
Du kan deklarera ombud med någon av följande metoder:
- Deklarera en ombudstyp och deklarera en metod med en matchande signatur:
// 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);
- Tilldela en metodgrupp till en ombudstyp:
// C# 2.0 provides a simpler way to declare an instance of NotifyCallback.
NotifyCallback del2 = Notify;
- Deklarera en anonym metod:
// Instantiate NotifyCallback by using an anonymous method.
NotifyCallback del3 = delegate(string name)
{ Console.WriteLine($"Notification received for: {name}"); };
- Använd ett lambda-uttryck:
// Instantiate NotifyCallback by using a lambda expression.
NotifyCallback del4 = name => { Console.WriteLine($"Notification received for: {name}"); };
Mer information finns i Lambda-uttryck.
I följande exempel visas hur du deklarerar, instansierar och använder ett ombud. Klassen BookDB
kapslar in en bokhandelsdatabas som underhåller en databas med böcker. Den exponerar en metod, ProcessPaperbackBooks
, som hittar alla pocketböcker i databasen och anropar ett ombud för var och en. Den delegate
typ som används heter ProcessBookCallback
. Klassen Test
använder den här klassen för att skriva ut rubrikerna och genomsnittspriset för pocketböckerna.
Användningen av ombud främjar en bra uppdelning av funktioner mellan bokhandelsdatabasen och klientkoden. Klientkoden har ingen kunskap om hur böckerna lagras eller hur bokhandelskoden hittar pocketböcker. Bokhandelskoden har ingen kunskap om vilken bearbetning som utförs på pocketböckerna när den hittar dem.
Exempel
// 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
*/
Robust programmering
Deklarera ett ombud.
Följande instruktion deklarerar en ny ombudstyp.
public delegate void ProcessBookCallback(Book book);
Varje ombudstyp beskriver antalet och typerna av argument och typen av returvärde för metoder som den kan kapsla in. När en ny uppsättning argumenttyper eller returvärdestyp behövs måste en ny ombudstyp deklareras.
Instansiera ett ombud.
När en ombudstyp har deklarerats måste ett ombudsobjekt skapas och associeras med en viss metod. I föregående exempel gör du detta genom att skicka
PrintTitle
metoden tillProcessPaperbackBooks
metoden som i följande exempel:bookDB.ProcessPaperbackBooks(PrintTitle);
Då skapas ett nytt ombudsobjekt som är associerat med den statiska metoden
Test.PrintTitle
. På samma sätt skickas den icke-statiska metodenAddBookToTotal
på objektettotaller
som i följande exempel:bookDB.ProcessPaperbackBooks(totaller.AddBookToTotal);
I båda fallen skickas ett nytt ombudsobjekt till
ProcessPaperbackBooks
metoden.När ett ombud har skapats ändras aldrig metoden som den är associerad med. delegera objekt är oföränderliga.
Anropa ett ombud.
När ett ombudsobjekt har skapats skickas ombudsobjektet vanligtvis till annan kod som anropar ombudet. Ett ombudsobjekt anropas med hjälp av namnet på ombudsobjektet, följt av de parentesbaserade argument som ska skickas till ombudet. Följande är ett exempel på ett ombudsanrop:
processBook(b);
Ett ombud kan antingen anropas synkront, som i det här exemplet, eller asynkront med hjälp
BeginInvoke
av ochEndInvoke
metoder.