|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IntroductionDelegates and Events are two very powerful features of .NET. Events are the cornerstone of GUI programming and Delegates are used in implementing them. In this article, I discuss briefly how delegates work and how they are made use of to implement events. Table of Contents
What is a delegate?Delegates in the .NET framework are equivalent to function pointers. However, the C# Language Specification also adds: "unlike function pointers, delegates are object oriented and type-safe”. Delegates allow you to pass references of entry points to methods and invoke them without making an explicit method call. It also defines the signature of the method it can call. For example: public delegate int MyDelegate(string somevalue);
This delegate may be used to invoke methods that return an integer and take a string as a parameter. In order to make use of this delegate, you need to instantiate it, to specify the method that needs to be called. For example: public void MyMethod()
{
MyDelegate a = new MyDelegate(MyDelegateMethod);
}
Here Note: If signatures of method and delegate do not match, the C# compiler reports an error such as: td.cs(38,46): error CS0123: Method 'DelegateDemo.SampleClient.MyEvent()'
does not match delegate 'void DelegateDemo.CustomTextEvent()'
A delegate is used to invoke a method similar to how a method call is made. For example: a(“This is a test invocation”);
Thus, there are three steps in defining and using delegates:
A complete example follows: using System;
namespace SimpleDelegateExample{
public delegate void SimpleDelegate();
class TestDelegate
{
public static void ActualFunction()
{
Console.WriteLine("called by delegate..");
}
public static void Main(){
SimpleDelegate sd = new SimpleDelegate(ActualFunction);
sd();
}
}// end class TestDelegate
}// end namespace SimpleDelegateExample
A couple of interesting points to note …A delegate 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. If an invoked method throws an exception, the method stops executing, the exception is passed back to the caller of the delegate, and remaining methods in the invocation list are not invoked. Catching the exception in the caller does not alter this behavior. How delegates work?The .NET framework documentation details how delegates work.
EventsThe C# programmer’s reference defines an event as follows:
Declaring an event is directly tied to a delegate. A delegate object encapsulates a method so that it can be called anonymously. An event is a mechanism by which a client class can pass in delegates to methods that need to be invoked whenever “something happens”. When it does, the delegate(s) given to it by its clients are invoked. To declare an event in C# use the following syntax: public delegate void testDelegate(int a);
public event testDelegate MyEvent;
Once an event is declared, it must be associated with one or more event handlers before it can be raised. An event handler is nothing but a method that is called using a delegate. Use the For example: Myform.MyEvent += new testEvent(MyMethod);
An event handler may also be detached as follows: MyForm.MyEvent -= new testEvent(MyMethod);
In C#, events may be raised by just calling them by a name similar to method invocation, say How does the event keyword work ?Whenever an event is defined for a class, the compiler generates three methods that are used to manage the underlying delegate… i.e.:
Delegates and Events in Windows FormsDefault delegates are provided for the events of the controls and classes of the .NET Framework base class library. When using Windows Forms to create rich client applications, events can be handled in two ways…
For example, the Registering event handlers with delegates:Declare a method with the same return types and arguments as the static void MyPaintHandler(object sender, PaintEventArgs pea){
// process
}
and then install this handler for a particular instance… myform.Paint += new PaintEventHandler(MyPaintHandler);
Overriding member functions:Inside a class derived from protected override void OnPaint(PaintEventArgs pea){
// process
}
At this point, it is quite natural to think that the base class method (which can be overridden to handle an event) is just an event handler, that has already been installed. It is actually the other way around. It is the responsibility of the base class method to actually invoke all the installed event handlers. Let me give an example to illustrate this point: using System;
using System.Windows.Forms;
namespace DelegateDemo{
public delegate void CustomTextEvent();
class CustomTextForm : Form
{
private string m_sText=null;
public event CustomTextEvent CustomTextChanged;
public string CustomText
{
get
{
return m_sText;
}
set
{
m_sText = value;
OnCustomTextChanged();
}
}
protected virtual void OnCustomTextChanged()
{
if(CustomTextChanged!= null)
CustomTextChanged();
}
}// end class CustomTextForm
class SampleClient
{
public static void Main(){
CustomTextForm a = new CustomTextForm();
a.CustomTextChanged += new CustomTextEvent(SampleClient.MyEvent);
a.CustomText = "Welcome !";
Application.Run(a);
}
public static void MyEvent()
{
Console.WriteLine("Custom text changed");
}
}// end class SampleClient
}// end namespace SampleDelegateDemo
Code Discussion:For the sake of discussion, assume you need to write a custom public event CustomTextEvent CustomTextChanged;
and the corresponding delegate is also defined: public delegate void CustomTextEvent();
There is also an event handling method of the base class (your class) that is called whenever this event occurs. This is given as: protected virtual void OnCustomTextChanged()
{
if(CustomTextChanged!= null)
CustomTextChanged();
}
The client class also registers a new event handler … a.CustomTextChanged += new CustomTextEvent(SampleClient.MyEvent);
When you run this sample, the Note: The following code is mandatory: if(CustomTextChanged!= null)
CustomTextChanged();
because The Further ReadingOnce you are quite familiar with delegates, you would find the following articles interesting:
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||