C# Tutorials and offshore development in India
    Tutorials   Resources   Forum   Communities   Interview   Jobs   Projects   Offshore Development    
Silverlight Tutorials | Mentor | Code Converter | Articles | Code Factory | Computer Jokes | Members | Peer Appraisal | IT Companies | Bookmarks | Revenue Sharing |


Prizes & Awards
My Profile



Active Members
TodayLast 7 Days more...

New Feature: Community Sites: Create your own .NET community website and start earning from Google AdSense ! It's Free !




Demystifying Delegates and Events in C#


Posted Date: 10 Jul 2007    Resource Type: Articles    Category: .NET Framework

Posted By: Prajnan Das       Member Level: Gold
Rating:     Points: 17



Introduction



When we declare a delegate; under the hood the compiler defines a class. When we declare an event, the compiler defines a private delegate instance and a property which encapsulates this instance through a set of add and remove accessors.

Delegates: the custom delegate class



Let us define a custom delegate and compile it:

public delegate int Processor(string str);


Under the hood; the compiler generates a custom delegate class which inherits from System.MulticastDelegate which, again, inherits from System.Delegate, both of which are abstract. System.Delegate implements the functionality of invoking a single method target. System.MulticastDelegate acts as a wrapper over System.Delegate to provide the functionality of invoking a chain of method targets. Three additional methods are defined by the compiler for a custom delegate class: BeginInvoke, EndInvoke and Invoke. If you do an ‘ildasm’ on your compiled project you can see these methods definitions as follows:


.method public hidebysig newslot virtual
instance class [mscorlib]System.IAsyncResult
BeginInvoke(string str,
class [mscorlib]System.AsyncCallback callback,
object 'object') runtime managed
{
} // end of method Processor::BeginInvoke

.method public hidebysig newslot virtual
instance int32 EndInvoke(class [mscorlib]System.IAsyncResult result) runtime managed
{
} // end of method Processor::EndInvoke

.method public hidebysig newslot virtual
instance int32 Invoke(string str) runtime managed
{
} // end of method Processor::Invoke


Constructor of a delegate:



The custom delegate class defines a parameterized constructor which accepts two parameters: an object and an IntPtr. The first argument identifies the target object instance against which the target method should be invoked. The second argument holds a pointer to the target method. Here is the MSIL code for the constructor pertaining to the delegate defined above:


.method public hidebysig specialname rtspecialname
instance void .ctor(object 'object',
native int 'method') runtime managed
{
} // end of method Processor::.ctor


The fact that the constructor takes an object instance just reiterates the object oriented aspect of delegates in C#: they are not mere function pointers but also have the capability of attached them to the instance against which the target method is to be invoked. Delegates can be used to call static methods as well, in which case the object parameter would be null.

Invocation of methods:



In the custom delegate class, BeginInvoke and Invoke methods are defined maintaining the delegate signature (single parameter string here). This is how delegates ensure type safety. Now let us define a class which would use Processor delegate:


namespace ClassLibrary
{
public class DelegatesEventsDemo
{
public void CallDelegates(string str)
{
Processor pd = new Processor(Parse);
//Call the delegate
pd(str);
}

private int Parse(string str)
{
return Int32.Parse(str);
}
}
}


If you look at the MSIL code for the CallDelegates method; you would see that the delegate invocation is translated to a call to the Invoke method:


callvirt instance int32 ClassLibrary.Processor::Invoke(string)


BeginInvoke and EndInvoke are used in asynchronous usage of delegates; which we won’t be discussing here.

Registration of delegates:



One of the capabilities of the delegates is to allow registration of multiple target methods. Let us define another method in our DelegatesEventsDemo class:


private int FindLength(string str)
{
return str.Length;
}


And have it registered in the CallDelegates method:


pd += new Processor(FindLength);


What happens behind the scene for this registration? Well; a call to the method Delegate.Combine is made; as revealed by the MSIL code below:


call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Combine(class [mscorlib]System.Delegate, class [mscorlib]System.Delegate)


It is to be noted that there is an additional field in a MulticastDelegate called prev which refers to another MulticastDelegate. What method Delegate.Combine does is that it combines the two delegates and makes second’s prev field point to first. It then returns the head of the linked list. Thus, when a delegate is added to a multicast delegate, the MulticastDelegate class creates a new instance of the delegate type, stores the object reference and the pointer for the target method into the new instance, and adds the new delegate instance as the next item in a list of delegate instances. In effect, the MulticastDelegate class maintains a linked list of delegate objects. A chain of delegate target is thus created.

Events



Events are property like constructs which the compiler generates when an event is declared. An event is basically a wrapping property over an existing private delegate instance field. The property exposes only add and remove accessors (that’s why you don’t see = operation available on an event). Let us declare an event in our DelegatesEventsDemo class:


public event Processor ProcessorEvent;


This would end up in having a MSIL code like this at the DelegatesEventsDemo class level:


.field private class ClassLibrary.Processor ProcessorEvent

.event ClassLibrary.Processor ProcessorEvent
{
.addon instance void ClassLibrary.DelegatesEventsDemo::add_ProcessorEvent(class ClassLibrary.Processor)
.removeon instance void ClassLibrary.DelegatesEventsDemo::remove_ProcessorEvent(class ClassLibrary.Processor)
} // end of event DelegatesEventsDemo::ProcessorEvent


So we are having a private field of the associated delegate type and a pair of add/ remove property constructs. This aids in registering/ removing “event handlers” against that event. If we dig further into the MSIL code; we can find MSIL code for the add and remove handlers is basically having call to Delegate.Combine and Delegate.Remove respectively. For brevity I have omitted remove_ProcessorEvent code, but it will be very similarly with the call to Combine being replaced by a call to Remove.


.method public hidebysig specialname instance void
add_ProcessorEvent(class ClassLibrary.Processor 'value') cil managed synchronized
{
// Code size 24 (0x18)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldarg.0
IL_0002: ldfld class ClassLibrary.Processor ClassLibrary.DelegatesEventsDemo::ProcessorEvent
IL_0007: ldarg.1
IL_0008: call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Combine(class [mscorlib]System.Delegate,
class [mscorlib]System.Delegate)
IL_000d: castclass ClassLibrary.Processor
IL_0012: stfld class ClassLibrary.Processor ClassLibrary.DelegatesEventsDemo::ProcessorEvent
IL_0017: ret
} // end of method DelegatesEventsDemo::add_ProcessorEvent


Summary


The fundamental aspect here is that delegates are basically classes and these classes inherit from System.MulticastDelegate; which provides them the capability of invoking multiple method targets and events are just properties over private delegate instances which allow only add and remove operations.




Responses

Author: chaithanya    14 Jul 2008Member Level: Silver   Points : 1
Hi,

Its a good article about Delegate and Events, as i am new to this concepts, this resource helped me to learn the usage of Delegates and Events.


Feedbacks      
Popular Tags   What are tags ?   Search Tags  
Events in C#  .  Demystifying Events in C#  .  Demystifying Delegates in C#  .  Demystifying Delegates and Events in C#  .  Demystifying Delegates and Events  .  Delegates in C#  .  Delegates and Events in C#  .  Delegates and Events Explained  .  

Post Feedback


This is a strictly moderated forum. Only approved messages will appear in the site. Please use 'Spell Check' in Google toolbar before you submit.
You must Sign In to post a response.
Next Resource: Biztalk Ports
Previous Resource: Thread-safe events
Return to Discussion Resource Index
Post New Resource
Category: .NET Framework


Post resources and earn money!
 
Related Resources



dotNet Slackers   BizTalk Adaptors    Web Design

internet fax

Contact Us    Privacy Policy    Terms Of Use