Ahmed El-Halwagy’s Blog

Archive for December 2008

Every .NET programmer has used delegates in a way or another and hopefully appreciated the flexibility delegates provide. A delegate is simply a type-safe, object oriented function pointer. A pointer that can points to a function and can be used to dynamically invoke methods. Take a look at the following example on how to use the old fashion function pointer.

#include <iostream>

using namespace std;

 

//Function prototypes.

int Add( int, int) ;

int Subtract ( int, int);

 

void main( void ) {

 

int firstNumber = 0;

int secondNumber = 0;

int result = 0;

char answer = ‘a’;

//The declaration of function pointer.

int (*funcPtr) (int, int);

 

cout << “Plz enter the first number !” << endl;

cin >> firstNumber;

cout << “Plz enter the second number !”<< endl;

cin >> secondNumber;

 

cout << “Add or Subtract (A/S) ?” << endl;

cin >> answer;

 

if(answer == ‘a’)

funcPtr = Add; // Assigning a function to the pointer.

else

funcPtr = Subtract;

//calling the function using the function pointer.

result = funcPtr(firstNumber, secondNumber);

 

cout << “The result is “ << result << endl;

getchar();

}

//actual functions implementation.

int Add( int x, int y) {

return x + y;

}

 

int Subtract( int x, int y) {

return x – y;

}

That’s a complete C++ program to demonstrate the use of a function pointer. As you can see I’ve declared a function pointer funcPtr that is ready to point to any function that returns integer and takes two integers as parameters.

int (*funcPtr) (int, int);

After declaring the pointer and prompting the user for input, it’s now time to assign a value to this pointer. As this pointer is declared to point to function, so the value assigned to it is a function. The syntax used to assign a value to the function pointer is:


PointerName = FunctionName; (i.e. funcPtr = Add;)

Now we have everything set, the function pointer is declared and is pointing to a valid function. We can now call that function using that pointer name (remember pointers are variables that holds the memory address of other variables or functions on the program, and can be used to indirectly access those variables values or call the target functions.) as follows:

result = funcPtr(firstNumber, secondNumber);

This line is used to indirectly invoke the method that funcPtr is pointing to and passing in two integer variables (firstNumber and secondNumber) and also holding the function’s return value in yet another integer variable called result. The benefit of using this technique (regardless of the clumsy syntax) is that you can determine function calls according to user input in a concise way. Delegates basically do more or less the same job but in a more cleaner way. If you took a look at the above example (specially at this line
int (*funcPtr) (int, int);) you would notice that I have declared a function pointer funcPtr that can point to any function that returns integer and accepts two intger parameters. The dangerous thing about that line is that, I have not initialized that pointer which makes it poiting to a random place in memory and if I called it right a way without assigning a value to it, it would most probably cause my program to crash. (PS: you can use the following syntax to initialize that pointer to NULL at first declaration
int (*funcPtr) (int, int) = NULL;).

If you tried to use that pointer (funcPtr) before assigning value to it, the compiler will simply let you go, it will not generate an error to warn you from the potential risk. This is the real bad thing about function pointers and pointers in general, they’re flexible and powerful, but they are NOT safe.

A delegate is a safe, object-oriented replacement to the old function pointer. You can use delegates to indirectly invoke methods both in synchronous mode and asynchronous mode. As you may know delegates in C# are types, like classes, interfaces, structs and enums. They can be declared on a namespace level so you can reuse them in all the types in that namespace and mybe even across namspaces inside the boundary of one assembly or cross assemblies. To declare a delegate you use the following syntax.

public delegate int BinaryDel(int x, int y);

Here we declared a delegate (modern function pointer) called BinaryDel that can point to any method that returns an integer and takes two integer parameters. To put this delegate in action take a look at the following example:

class Program {

static void Main(string[] args) {

//Instantiating a new BinaryDel object

BinaryDel myDel = new BinaryDel(Add);

int result = myDel(5, 6);

Console.WriteLine(“The result is {0}”, result);

Console.ReadLine();

 

}

 

static int Add(int x, int y) {

return x + y;

}

 

static int Subtract(int x, int y) {

return x – y;

}

}

As you can see here, the first thing I’ve done in order to use this BinaryDel is to instantiate a new instance of this delegate using the new keyword and passing in a method name in the constructor. This is the name of the method that myDel (the instance of BinaryDel) will be pointing to. For now delegates do not have a lot to offer more than function pointer except for the type-safety that is provided through the compile-time check. Delegates are more than that, a delegate can point to more than one method and invoke them all respectfully. Each delegate itself is a class that extends the System.MulticastDelegate class, this class has a collection called invocation list which is a collection of .. well .. delegates. You can use the (+=)operator on any instance of a delegate to add method addresses to that invocation list and later then you can call them all.

class Program {

static void Main(string[] args) {

//Instantiating a new BinaryDel object

BinaryDel myDel = new BinaryDel(Add);

myDel += new BinaryDel(Subtract);

myDel += Multiply;

 

int result = myDel(5, 6);

Console.ReadLine();

 

}

 

static int Add(int x, int y) {

Console.WriteLine(“Inside Add method”);

return x + y;

}

 

static int Subtract(int x, int y) {

Console.WriteLine(“Inside Subtract method”);

return x – y;

}

static int Multiply(int x, int y) {

Console.WriteLine(“Inside Multiply method”);

return x * y;

}

}

That’s an update to the first example. In this example I’ve updated the Add and Subtract methods to print a line to the console indicating that each of them has been called. I also added a brand new method called multiply that also returns an integer and takes two integer parameters (i.e. matches the delegate signature.)I then used the += operator to add both Subtract and Multiply methods to the invocation list of myDel. Now myDel points to three methods Add which is passed to it in the constructor, Subtract, and Multiply that are added to it using the += operator.


PS: when using the += operator on a delegate instance, it expects another instance of the same delegate to be added to the invocation list of the left side delegate of the assignment. So at the first time I used the syntax (myDel += new BinaryDel(Subtract);) to add new instance of BinaryDel pointing to Subtract to the invocation list of my current instance myDel, this is the expected behavior because as you may recall I mentioned that each delegate’s invocation list is simply a list of the same delegate items, each of which points to one or more methods. However, the syntax I used next is different than that
(myDel += Multiply;). This is the same as the previous syntax. The compiler here will create a new instance of BinaryDel pointing to Multiply and then will add that instance to the invocation list of myDel. It’s also worth mentioning that you can remove method addresses from any delegates invocation list using the -= operator. Consult the .NET framework documentation for more details.

When calling these methods using myDel like so myDel(5, 6); they will be called in order meaning that the Add method will be called first then the Subtract then the Multiply (you may know guess that the invocation list of myDel is implemented as a Queue .. smart cookie J ). Now the question is “What is the value of result?” the answer is “The value of result is the return value of the last method in the invocation list, in our case multiply.

One more feature of delegates is that they provide the ability to invoke methods asynchronously throught the delegates bulit in method BeginInvoke. BeginInvoke will invoke the methods on a new background thread, and the main thread will keep executing at the same time, then when you are ready to receive the return of that method you called by the delegate you can call EndInvoke on the very same delegate. You can also provide an AsyncCallBack delegate that point to some method –Say A- as a parameter to begin invoke, this method –A- will be called automatically after the execution on the background thread ends. or further details consult the .NET framework decumentation.

Delegates can also be used as function parameters and function return types. However, the primary usage for delegates in the .NET universe is to subscribe to events. An event is a flag raised by an object to indicate the various phases of the object life cycle. Assume we have a class called Employee that represents an actual employee. We will use events to flag some key time-points in the employee life cycle, points like when the employee gets hired or when picked for an external mission or when he or she gets fired. The code for the employee class my more or less look like this:

//Custom delegate to use for the employee events.
public delegate void EmployeeDel(Employee e, string action);

 

public class Employee {

//Creating the events.

public event EmployeeDel OnGettingARaise = null;

public event EmployeeDel OnPromoting = null;

 

public int Age { get; set; }

public float Salary { get; set; }

public string Name { get; set; }

public string Position { get; set; }

 

public void ShowDirectMangerSomeLove() {

Console.WriteLine(“EMployee>> Mr Manager .. you’re the best 🙂 .. !”);

Console.WriteLine(“Manger>> thanks {0} you got a raise !”, this.Name);

//Increasing the salary by 5

this.Salary += 5;

//Raising the event if there are any subscribers.

if (OnGettingARaise != null)

OnGettingARaise(this, “Having a raise”);

}

 

public void ShowCEOSomeLove() {

Console.WriteLine(“>>Employee: Mr CEO .. You’re leading us right to the top”);

Console.WriteLine(“>>CEO: thanks {0} .. you know what .. I really think you should be in a higher position”, this.Name);

this.Position = “Manager”;

this.Salary += 200;

//raising the event if there’s any subscribers.

if (this.OnPromoting != null)

OnPromoting(this, “Got promoted !”);

}

}

Here I have declared a custom delegate called EmployeeDel that can point to any method that returns void and takes an Employee and a string as parameters. Then inside the Employee class declaration I created two events OnGettingARaise and OnPromoting, both using the EmployeeDel delegate. In the ShowDirectManagerSomeLove() method I raise the OnGettingARaise event passing in the current object and a string indicating that the employee has a raise, I then increase the employee’s salary as a result of showing his manager some love J. As you notice here because the OnGettingARaise event is declared of type EmployeeDel, it has to pass in the required parameters for this EmployeeDel (Employee, string) when it’s being raised. To see this Employee class in action, take a look at the following:

class
Program {

static void Main(string[] args) {

Employee shankl = new Employee() {

Name = “Shankl Shankool”,

Age = 30,

Salary = 2000f,

Position = “Sales Man”

};

 

shankl.OnGettingARaise += new EmployeeDel(HandleEmployeeGettingARaise);

shankl.ShowDirectMangerSomeLove();

 

}

static void HandleEmployeeGettingARaise(Employee e,

string action) {

Console.WriteLine(

“{0} who works as {1} has got a raise .. \nhis salary now is {2}”,

e.Name, e.Position, e.Salary);

}

}

The program class containing the Main method defines a method called HandleEmployeeGettingARaise that matches the EmployeeDel delegate singuature as it returns void and takes two input parameters (Employee, string). This method can be used to handle the OnGettingARaise and OnPromoting events for the employee class as it matches the type of these events (EmployeeDel). In Main I’ve declared a new Employee with the name “Shankl Shakol” and 30 years of Age and 2000$ salary and works as a “Sales Man” using the object initializaiton syntax. The next line is the line where I subscribe to the OnGettingARaise event of the Employee object-shankl-and provide delegate of the type EmployeeDel that points to my HandleEmployeeGettingARaise method. This means that when this event is raised my handler (HandleEmployeeGettingARaise mehtod) will be executed. Run the code and examine it yourself.


Calendar

December 2008
S M T W T F S
« Nov   Jan »
 123456
78910111213
14151617181920
21222324252627
28293031  

Categories

Delicious

Recent Twitter Updates

  • RT @MattChorley: Bring your child to work day https://t.co/QOptwEmsZ0 1 week ago
  • RT @shawky281: الواحد حاسس بفاجعة الحدث و خطورته على الجيش نفسه ككيان اكتر من موالسين الدولجية اللي صدعوا اهالينا بقالهم 6 سنين عن قدسية عم… 1 week ago
  • RT @gamaleid: ولا واحد ، ولا نص ، ولا ربع عضو من بتوع 25/30 اعلن تقديم استقالته! حار بارد ممطر جاف 1 week ago
  • RT @MalekAdly: حزب النور موافق علي إن الجزر تضيع .. طب اعتبروها كاميليا اختكم حتي #تيران_وصنافر_مصرية 1 week ago
  • RT @AmrEzzat: غلاف الأخبار اللبنانية: باع أرضه https://t.co/PfGeaLLexT 1 week ago