C# Delegates Explained - Callback Methods through Delegates
(Page 5 of 5 )
Callback methods illustrate the usefulness of delegates. The callback mechanism may seem unusual at first, but it provides a great functionality which illustrates the delegation of a task to another object. To explain what a callback method is and how we can use it, I'm introducing the following example:
using System;
namespace MyCompany
{
public class Employee
{
private string firstName;
private string lastName;
private decimal salary;
public Employee(string first, string last, decimal salary)
{
this.firstName = first;
this.lastName = last;
this.salary = salary;
}
public string FirstName
{
get {return firstName;}
set {firstName = value;}
}
public string LastName
{
get {return lastName;}
set {lastName = value;}
}
public decimal Salary
{
get {return salary;}
set {salary = value;}
}
public override string ToString()
{
return String.Format("{0} {1} with a payroll of {2}",
firstName,lastName, salary);
}
}
public class Department
{
private Employee[] emps;
private string name;
public Department(Employee[] theEmps, string name)
{
emps = theEmps;
this.name = name;
}
public string Name
{
get
{
return name;
}
}
// declaring a nested delegate type that accepts an Employee instance
public delegate void EmployeeCallback(Employee emp);
// This method accepts an EmployeeCallback instance thus
// providing the Callback mechanism
public void ProcessEmployees(EmployeeCallback callback)
{
foreach(Employee emp in emps)
{
callback(emp);
}
}
}
public class Sys
{
private static void UpdatePayroll(Employee emp)
{
emp.Salary *= 1.2m;
Console.WriteLine("The Employee {0} {1}'s salary increased to {2}",
emp.FirstName,emp.LastName,emp.Salary);
}
public static void Main()
{
Employee emp1 = new Employee("Marina", "Joe", 7000m);
Employee emp2 = new Employee("Mina", "Nader", 7000m);
Employee emp3 = new Employee("Johny", "Hany", 9000m);
Employee[] emps = new Employee[3];
emps[0]= emp1;
emps[1]= emp2;
emps[2]= emp3;
Department dep = new Department(emps,"IT");
foreach(Employee emp in emps)
{
Console.WriteLine(emp.ToString());
}
Console.WriteLine("nCreating the delegate object");
// creating the delegate instance
Department.EmployeeCallback updateCallback =
new Department.EmployeeCallback(UpdatePayroll);
Console.WriteLine("calling the method ProcessEmployees()n");
dep.ProcessEmployees(updateCallback);
Console.ReadLine();
}
}
}

The above namespace contains three classes: Employee, Department and Sys. Before I explain anything I have to say that "The Department class DELEGATES the task of updating the Employees' salaries to the Sys class through the use of a Callback method". Let me explain how it's done.
The Employee class is a simple class with three private fields (firstName, lastName and salary), a Constructor to initialize those fields, and three properties to access the private fields. It overrides the ToString() method. The Department class contains a private array of type Employee and another private field of type string to store the name of the department.
The Constructor initializes those fields and also a public property for the name field. The fun begins at the declaration of the delegate EmployeeCallback, which encapsulates any method that accepts one argument of type Employee. The fun continues with the method ProcessEmployees(EmployeeCallback callback). As you can see this method accepts an EmployeeCallback delegate.
The implementation of this method is very simple. Its foreach statement invokes the passed delegate on each Employee instance stored in the private array. The Sys class has a static method called UpdatePayroll which accepts an Employee instance and then update its salary and prints the current salary to the console.
The Main() method creates three Employee instances then assigns those instances to the emps array. The next statement creates an object of type Department and passes the emps array as an argument to the Constructor in order to initialize the internal Employee array of the Dep object. The foreach statements iterate through the Employee instances, calling their ToString() method which prints the firstName, lastName and the salary of the employee.
We then create a new instance of the type EmployeeCallback called updateCallback, which encapsulates the private static method UpdatePayroll. The last statement calls the method ProcessEmployees() and passes the delegate instance as an argument to the method. The call to the method ProceeEmployees() does the trick of the Callback. If you step into the code of this method you will notice that this method calls the UpdatePayroll() method (although it's a private method of the class Sys) for each Employee instance (through the delegate) of the emps array of the dep object.
So callback methods introduce a way to make a conversation between objects. The Sys class calls the ProcessEmployees() method which in turn calls the private method Sys.UpdatePayroll() through the delegate for each Employee instance to update his salary. So we say that the dep object is delegating the functionality of updating the employees' salaries to the class Sys through a callback method.
To provide the callback mechanism you need to create a delegate and a method that accepts the delegate as a parameter as we did in our example. There are other situations where we can use callback methods like asynchronous calls.
| DISCLAIMER: The content provided in this article is not warranted or guaranteed by Developer Shed, Inc. The content provided is intended for entertainment and/or educational purposes in order to introduce to the reader key ideas, concepts, and/or product reviews. As such it is incumbent upon the reader to employ real-world tactics for security and implementation of best practices. We are not liable for any negative consequences that may result from implementing any information covered in our articles or tutorials. If this is a hardware review, it is not recommended to open and/or modify your hardware. |