Delegate
C # commissioned similar to the function pointer in C or C . Use the entrustment to make the programmer to encapsulate the method within the delegate object. You can then pass the delegate object to the code that can be called, without having to know which method will be called when compiling. Unlike the function pointers in C or C , the delegate is object-oriented, safe, and is safe.
The delegate declaration defines a type that uses a specific parameter and the return type package method. For static methods, the method of delegate the object package to be called. For example methods, the delegate object simultaneously encapsulates an example and a method on this instance. If you have a delegate object and a set of appropriate parameters, you can call the delegate with these parameters.
A interesting and useful attribute entrusted is that it does not know or not care about the object of the object you reference. Any object can be; just the parameter type and return type of the method must match the parameter type and return type of the delegate. This makes the commission fully suitable for "anonymous" calls.
This tutorial includes two examples:
Example 1 shows how to declare, instantiate and call delegates.
Example 2 shows how to combine two delegates.
In addition, the following topics are discussed:
Entrusted and incident
Entrusted and interface
Example 1
The following example illustrates the declaration, instantiation and use. BookDB classes package a bookstore database that maintains a book database. It discloses the ProcessPaperbackBooks method, which looks for all the paperback books in the database and calls a delegate for each book. The delegate type used is called ProcessBookDelegate. Test class uses this class to output the book name and average price of the sheetset.
The use of the entrusted use promotes a good separation between the bookstore database and the customer code. Customer code doesn't know how books are stored and the bookstore code looks for the way. The bookstore code does not know what will be processed after the paperback book is found.
// BookStore.cs
Using system;
// 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 data.
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 PrerespondoTotaller
{
INT countryBooks = 0;
Decimal pricebooks = 0.0m;
Internal Void AddbooktotAl (Book Book)
{
Countbooks = 1;
PriceBooks = BOOK.PRICE;
}
INTERNAL DECIMAL AVERAGEPRICE ()
{
Return Pricebooks / CountBooks and COUNTBOOks;
}
}
// Class to Test The Book Database:
Class test
{
// Print The title of the book.
Static void PrinTtitle (Book B)
{
Console.writeline ("{0}", b.title);
}
// Execution starts here.
Static void
Main
()
{
BookDB boxdb = 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.ProcessPaperbackBookBookBookBooks (New ProcessBookDelegate (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 Addbooktotal on The Object Totaller:
BookDb.ProcessPaperbackBookBooks (New ProcessBookDELEGATE (Totaller.Addbooktotal);
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
Code discussion
Declare the following statement:
Public Delegate Void ProcessBookDelegate (Book book);
Declare a new entrustment type. Each delegate type describes the number and type of parameters, and the return value type of how it can be packaged. Whenever a set of new parameter types or new return value types must be declared, a new entrustment type must be declared.
After instantiate the entrustment statement, it must create a delegate object and associate with a particular method. Similar to all other objects, the new delegate object is created with New Expressions. But when you create a delegate, the parameters pass to the New Expression are very special: its writing is similar to the method call, but there is no method.
The following statement:
BookDb.ProcessPaperbackBookBookBookBooks (New ProcessBookDelegate (PrintTitle);
Create a new delegate object associated with the static method Test.printTitle. The following statement:
BookDb.ProcesspaperpaperbackBooks (New
ProcessBookDelegate (Totaller.Addbooktota);
Create a new delegate object associated with non-static ways ADDBOOKTOTOTAl on Totaller. In two examples, the new delegate object is immediately passed to the ProcessPaperBackBooks method.
Note Once the delegate is created, the method it associated will never change: the delegate object cannot be changed.
After the delegate creates a delegate object, the delegate object is usually passed to other code that will call the delegate. Call the entrustment object by the name of the delegate object (behind follow the parameters to be transmitted to the entrusted). Below is an example of a delegate call:
ProcessBook (b);
Example 2
This example demonstrates a combination of entrusted. A useful attribute of the entrusted object is that they can " " operators to combine. A combination of delegate sequentially call two delegates that make it. Only the same type of delegate can only be combined, and the delegate type must have a VOID return value. The "-" operator can be used to remove the component from the entrustment to the combination.
// Compose.cs
Using system;
Delegate void mydelegate (string s);
Class myclass
{
Public Static Void Hello (String S)
{
Console.writeline ("Hello, {0}!", S);
Public Static Void Goodbye (String S)
{
Console.writeline ("Goodbye, {0}!", S);
}
Public static void
Main
()
{
MyDelegate A, B, C, D;
// Create the Delegate Object a That References
// the method hello:
a = new mydelegate (hello);
// Create the Delegate Object B That References
// the method goodbye:
B = new mydelegate (goodbye);
// The Two delegates, A and B, Are Composed to Form C,
// Which Calls Both Methods in Order:
C = a b;
// Remove a from the composed delegate, Leaving D,
// Which Calls Only The Method Goodbye:
D = C - a;
Console.writeline ("Invoking Delegate A:");
A ("a");
Console.writeline ("Invoking Delegate B:");
b ("b");
Console.writeline ("Invoking Delegate C:");
C ("c");
Console.WriteLine ("Invoking Delegate D:");
D ("d");
}
}
Output
Invoking delegate A:
Hello, A!
Invoking Delegate B:
Goodbye, B!
Invoking delegate C:
Hello, C!
Goodbye, C!
Invoking delegate D:
Goodbye, D!
Entrusted and incident
The delegate is ideal for use as an event (from a component to notify "listener").
Entrusted and interface
The similarity of commission and interface is that they all allow separation specifications and implementation. Multiple independent authors can generate multiple implementations compatible with an interface specification. Similarly, the signature of the assignment method, multiple authors can write multiple methods compatible with the delegate specification. When should I use, when should I use delegate?
Entrust it in the following cases:
Call a single method.
A class may wish to have a number of implementations that have a method specification.
It is desirable to use static methods to implement specifications.
I hope that the design pattern of similar events.
The caller does not need to know or obtain an object to define the method there.
The implementation provider wants to implement only the "distribution" specification for the minority component.
It takes a convenient combination.
The interface is useful in the following cases:
A specification definition will call a set of related methods.
Categories usually only achieve norms.
The caller of the interface wants to convert to interface types or converted from interface types to get other interfaces or classes.