A delegate in C# is similar to a function pointer in C or C++. Using a delegate allows the programmer to encapsulate a reference to a method inside a delegate object. The delegate object can then be passed to code which can call the referenced method, without having to know at compile time which method will be invoked. Unlike function pointers in C or C++, delegates are object-oriented, type-safe, and secure.
A delegate declaration defines a type that encapsulates a method with a particular set of arguments and return type. For static methods, a delegate object encapsulates the method to be called. For instance methods, a delegate object encapsulates both an instance and a method on the instance. If you have a delegate object and an appropriate set of arguments, you can invoke the delegate with the arguments.
An interesting and useful property of a delegate is that it does not know or care about the class of the object that it references. Any object will do; all that matters is that the method's argument types and return type match the delegate's. This makes delegates perfectly suited for "anonymous" invocation.
Note Delegates run under the caller's security permissions, not the declarer's permissions.This tutorial includes two examples:
- Example 1 shows how to declare, instantiate, and call a delegate.
- Example 2 shows how to combine two delegates.
- Delegates and Events
- Delegates vs. Interfaces
A delegate is a type-safe object that can point to another method (or possibly multiple methods) in the application, which can be invoked at later time.
Delegates also can invoke methods Asynchronously.
A delegate type maintains three important pices of information :
when you want to create a delegate in C# you make use of delegate keyword.
The name of your delegate can be whatever you desire. However, you must define the delegate to match the signature of the method it will point to. fo example the following delegate can point to any method taking two integers and returning an integer.
public delegate int DelegateName(int x, int y);
A Delegate Usage Example
A Multicast Delegate Example
The use of delegates promotes good separation of functionality between the bookstore database and the client code. The client code has no knowledge of how the books are stored or how the bookstore code finds paperback books. The bookstore code has no knowledge of what processing is done on the paperback books after it finds them.
I hope you are now have a good idea with the creation and usage of delegates types.
Delegates also can invoke methods Asynchronously.
A delegate type maintains three important pices of information :
- The name of the method on which it make calls.
- Any argument (if any) of this method.
- The return value (if any) of this method.
when you want to create a delegate in C# you make use of delegate keyword.
The name of your delegate can be whatever you desire. However, you must define the delegate to match the signature of the method it will point to. fo example the following delegate can point to any method taking two integers and returning an integer.
public delegate int DelegateName(int x, int y);
A Delegate Usage Example
namespace MyFirstDelegate
{
//This delegate can point to any method,
//taking two integers and returning an
//integer.
public delegate int MyDelegate(int x, int y);
//This class contains methods that MyDelegate will point to.
public class MyClass
{
public static int Add(int x, int y)
{
return x + y;
}
public static int Multiply(int x, int y)
{
return x * y;
}
}
class Program
{
static void Main(string[] args)
{
//Create an Instance of MyDelegate
//that points to MyClass.Add().
MyDelegate del1 = new MyDelegate(MyClass.Add);
//Invoke Add() method using the delegate.
int addResult = del1(5, 5);
Console.WriteLine("5 + 5 = {0}\n", addResult);
//Create an Instance of MyDelegate
//that points to MyClass.Multiply().
MyDelegate del2 = new MyDelegate(MyClass.Multiply);
//Invoke Multiply() method using the delegate.
int multiplyResult = del2(5, 5);
Console.WriteLine("5 X 5 = {0}", multiplyResult);
Console.ReadLine();
}
}}
Delegate ability to Multicast
Delegate's ability to multicast means that a delegate object can maintain a list of methods to call, rather than a single method
if you want to add a method to the invocation list of a delegate object , you simply make use of the overloaded += operator, and if you want to remove a method from the invocation list you make use of the overloaded operator -= .
Note: The Multicast delegate here contain methods that return void, if you want to create a multicast delegate with return type you will get the return type of the last method in the invocation list.
Delegate ability to Multicast
Delegate's ability to multicast means that a delegate object can maintain a list of methods to call, rather than a single method
if you want to add a method to the invocation list of a delegate object , you simply make use of the overloaded += operator, and if you want to remove a method from the invocation list you make use of the overloaded operator -= .
Note: The Multicast delegate here contain methods that return void, if you want to create a multicast delegate with return type you will get the return type of the last method in the invocation list.
A Multicast Delegate Example
namespace MyMulticastDelegate
{
//this delegate will be used to call more than one
//method at once
public delegate void MulticastDelegate(int x, int y);
//This class contains methods that MyDelegate will point to.
public class MyClass
{
public static void Add(int x, int y)
{
Console.WriteLine("You are in Add() Method");
Console.WriteLine("{0} + {1} = {2}\n", x, y, x + y);
}
public static void Multiply(int x, int y)
{
Console.WriteLine("You are in Multiply() Method");
Console.WriteLine("{0} X {1} = {2}", x, y, x * y);
}
}
class Program
{
static void Main(string[] args)
{
//Create an Instance of MulticastDelegate
//that points to MyClass.Add().
MulticastDelegate del = new MulticastDelegate(MyClass.Add);
//using the same instance of MulticastDelegate
//to call MyClass.Multibly() by adding it to it's
//invocation list.
del += new MulticastDelegate(MyClass.Multiply);
//Invoke Add() and Multiply() methods using the delegate.
//Note that these methods must have a void return vlue
Console.WriteLine("****calling Add() and Multibly() Methods.****\n\n");
del(5, 5);
//removing the Add() method from the invocation list
del -= new MulticastDelegate(MyClass.Add);
Console.WriteLine("\n\n****Add() Method removed.****\n\n");
//this will invoke the Multibly() method only.
del(5, 5);
}
}
}
Delegate Covariance
Assume you are designing a delegate that can point to methods returning a custom class type:
//Define a delegate pointing to methods returning Employee types.
Delegate Covariance
Assume you are designing a delegate that can point to methods returning a custom class type:
//Define a delegate pointing to methods returning Employee types.
public delegate Employee EmployeeDelegate();
if you were to derive a new class from Employee Type named SalesEmployee and wish to create a delegate type that can point to methods returning this class type you would be required to define an entirely new delegate to do so
if you were to derive a new class from Employee Type named SalesEmployee and wish to create a delegate type that can point to methods returning this class type you would be required to define an entirely new delegate to do so
//a new delegate pointing to methods returning SalesEmployee types.
public delegate SalesEmployee SalesEmployeeDelegate();
Example
Example
namespace MyEmployeesDelegate
{
//Define a delegate pointing to methods returning Employee types.
public delegate Employee EmployeeDelegate();
//a new delegate pointing to methods returning SalesEmployee types.
public delegate SalesEmployee SalesEmployeeDelegate();
class Program
{
public static Employee GetEmployee()
{
return new Employee();
}
public static SalesEmployee GetSalesEmployee()
{
return new SalesEmployee();
}
static void Main(string[] args)
{
EmployeeDelegate empDel = new EmployeeDelegate(GetEmployee);
Employee emp = empDel();
SalesEmployeeDelegate salesEmpDel = new SalesEmployeeDelegate(GetSalesEmployee);
SalesEmployee emp2 = salesEmpDel();
}
}
public class Employee
{
protected string firstName;
protected string lastName;
protected int Age;
public Employee()
{ }
public Employee(string fName, string lName, int age)
{
this.firstName = fName;
this.lastName = lName;
this.Age = age;
}
}
public class SalesEmployee : Employee
{
protected int salesNumber;
public SalesEmployee()
{ }
public SalesEmployee(string fName, string lName, int age, int sNumber): base(fName, lName, age)
{
this.salesNumber = sNumber;
}
}
}
It would be ideal to build a single delegate type that can point to methods returning either Employee or SelesEmployee types.
Covariance allows you to build a single delegate that can point to methods returning class types related by classical inheritance.
Delegate Covariance Example
It would be ideal to build a single delegate type that can point to methods returning either Employee or SelesEmployee types.
Covariance allows you to build a single delegate that can point to methods returning class types related by classical inheritance.
Delegate Covariance Example
namespace DelegateCovariance
{
//Define a single delegate that may return an Employee
// or SalesEmployee
public delegate Employee EmployeeDelegate();
class Program
{
public static Employee GetEmployee()
{
return new Employee();
}
public static SalesEmployee GetSalesEmployee()
{
return new SalesEmployee();
}
static void Main(string[] args)
{
EmployeeDelegate emp = new EmployeeDelegate(GetEmployee);
Employee emp1 = emp();
EmployeeDelegate empB = new EmployeeDelegate(GetSalesEmployee);
//to obtain a derived type you must perform an explicit cast.
SalesEmployee emp2 = (SalesEmployee)empB();
}
}
public class Employee
{
protected string firstName;
protected string lastName;
protected int Age;
public Employee()
{ }
public Employee(string fName, string lName, int age)
{
this.firstName = fName;
this.lastName = lName;
this.Age = age;
}
}
public class SalesEmployee : Employee
{
protected int salesNumber;
public SalesEmployee()
{ }
public SalesEmployee(string fName, string lName, int age, int sNumber): base(fName, lName, age)
{
this.salesNumber = sNumber;
}
}
}
Example 1
The following example illustrates declaring, instantiating, and using a delegate. TheBookDB
class encapsulates a bookstore database that maintains a database of books. It exposes a methodProcessPaperbackBooks
, which finds all paperback books in the database and calls a delegate for each one. The delegate type used is called ProcessBookDelegate
. The Test
class uses this class to print out the titles and average price of the paperback books.The use of delegates promotes good separation of functionality between the bookstore database and the client code. The client code has no knowledge of how the books are stored or how the bookstore code finds paperback books. The bookstore code has no knowledge of what processing is done on the paperback books after it finds them.
// 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 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 Test { // Print the title of the book. static void PrintTitle(Book b) { 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: Console.WriteLine("Paperback Book Titles:"); // Create a new delegate object associated with the static // method Test.PrintTitle: bookDB.ProcessPaperbackBooks(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 AddBookToTotal on the object totaller: bookDB.ProcessPaperbackBooks(new ProcessBookDelegate(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
I hope you are now have a good idea with the creation and usage of delegates types.
No comments :
Post a Comment