Home > SOA Tips > .NET Developer > What is a delegate in .NET?
SOA Tips:
EMAIL THIS
 TIPS & NEWSLETTERS TOPICS 

.NET DEVELOPER

What is a delegate in .NET?


Jim Culbert, .NET Technologies Expert
06.05.2003
Rating: --- (out of 5)


Digg This!    StumbleUpon Toolbar StumbleUpon    Bookmark with Delicious Del.icio.us   


Q. In .NET, what is a delegate? When would I want to use them? How are they best implemented? What are the "gotchas"?

A. Delegates are fun. If you've been programming for any length of time, you've been introduced to the concept of delegates as function pointers. As a quick review, pointers are used to store the address of a thing. By changing the address contained in a pointer, the same pointer can reference multiple things during the course of execution of a program. Thus, a pointer named "stackTop" can point to an infinite number of things as they are pushed and popped from a stack implementation. We are most familiar with pointers pointing to pieces of information. However, since pointers just store addresses under the covers, they can point to other program data as well. In particular a pointer can store the location of a function entry point and a programmer can use the pointer to instruct a computer to execute at the location stored in the pointer. Typically, the role of telling the computer how to hop around is relegated to the compiler and all the jumps are determined before the program starts running. However, it is sometimes not possible to know all the jumps when a program is compiled and the jumps need to be determined by a program as it executes. This is where we typically use function pointers.

I've said more about pointers than most folks need, I'm sure.

Delegates behave similarly to function pointers in C and C++. In C a programmer can create a type-safe pointer to a function and store those pointers just like any other pointer. These pointers can be assigned and later used to call the functions they reference. In C++ and other object languages, things get a bit more tricky. In object-oriented languages, most function processing is done in the context of an object instance (method call). Consider the case where a class implements a generic print function that takes no arguments and returns void. Let's consider further that call


Digg This!    StumbleUpon Toolbar StumbleUpon    Bookmark with Delicious Del.icio.us   


RELATED CONTENT
Microsoft .NET Web services
How do I balance throughput requirements and interoperability?
APM software traces transactions across tiers, technologies
How you can learn M Grammar for Oslo modeling
Legacy modernization opens Windows for publisher
Former .NET Web developers ride Ruby and Rails application framework
Microsoft Oslo at PDC: Dial 'M' for modeling language
Yahoo proxy fight looms
New Microsoft site for architects
LAMP coders go hybrid route
Silverlight shines on bank RIAs
Microsoft .NET Web services Research

.NET Developer
Programming Indigo
DataSets and Web services don't mix
Security in .NET 2.0
Tracking down managed memory leaks
Handling exceptions in .NET
.NET Compact Framework graphics
The Data Access Application Block
A great .NET resource: .Net2TheMax
Delegates vs. interfaces in .NET
Project structure best practices

RELATED GLOSSARY TERMS
Terms from Whatis.com − the technology online dictionary
Common Language Infrastructure  (SearchSOA.com)
Visual J#  (SearchSOA.com)

RELATED RESOURCES
2020software.com, trial software downloads for accounting software, ERP software, CRM software and business software systems
Search Bitpipe.com for the latest white papers and business webcasts
Whatis.com, the online computer dictionary


ing the print function on an object instance emits the object's state information to the console. Now let's consider that we create a pointer to the print function where the pointer's definition is "a function that takes no arguments and returns void". Now we go along and tell the computer to jump to this function pointer. At jump time, the only information available to the computer is the jump location in our definition. The problem is that to print the state information out for the object, you need the object!! In fact, if you go and muck about in the code generated by a C++ compiler, you will see that every (non static) method call includes a hidden argument which is a pointer to the object instance that the method is being called upon. So, to represent a pointer to a method in a particular object, you need not one but two pieces of information, the location where the computer is supposed to jump to and the object that the method is supposed to work on. The implementers of the C++ language chose to dodge implementing instances of pointers to member functions (note that I said instances of pointers to members...) deciding, in a nutshell, that it opened both a philosophical and practical can of worms.

C# has embraces the worms and implements a mechanism for creating pointers to specific functions on specific objects. Given all the introductory blather above, you should be able to guess pretty much what they do. Here are the important bits. Delegates encapsulate both the pointer to the method and the object context of the method (i.e., pointer to the object), where latter is never exposed to the programmer. In addition, and this is particularly interesting, a delegate can be assigned any other delegate where the method signatures match. At first blush this may not seem too interesting but consider an object that delegates its print method. For arguments sake, let's assume the object class is a "Document" class. Let's also assume that the class exposes a public delegate that can be assigned to print methods. When the document's print method is called, it calls the delegate to do its dirty work. Now let's assume we have a "CanOpener" class that also implements a print method that has the same signature as the delegate to which document delegates its printing. We can create a delegate from the CanOpener print method and assign that to the Document's print delegate! Woohoo! Lots of fun!

Here is some code that might make things clearer.

The output generated by this code is shown below

This is a toy example of course. A more common use of delegates is when an object implements a callback mechanism that others can "register" with. Implementing event notification registration typically entails having your callback placed on a list of callback methods that get invoked when an event occurs. When events occur, the "event generating" object calls all the callbacks in its callback list. The event generating object doesn't care about any details of the called object other than the signature of its callback.

Given that one of the uses for delegates is to support event handling, a feature was added to delegates to encapsulate this "list of callback functions" idiom. Delegates implement a capability that allows multiple delegates to be combined into a single instance. Invoking this composite delegate causes each of the composite members to be invoked. The "+", "-", "+=" and "-=" operators are overloaded to support delegate aggregation. The process of invoking a composite delegate and having the individual delegates invoked is often referred to "multicasting".

Consider the following implementation of the Main() method from our example above (previous comments stripped). The output from this would be:

You can see here that the first and second invocations create the same output (lines 1 & 2). The last two lines however, are the result of multicasting the invocation of the print delegate to the combination of the delegates created from both the JimDoc and DocumentPrinter print function delegates.

Finally, for your added benefit, we'll throw in the Ginsu-knives and some additional information about events. Events are a special qualification that can be applied to delegates. Declaring a delegate to be an event restricts the operations allowed on the event delegate outside of the context of the enclosing class. It is only possible to invoke the "+=" and "-=" operators on an event. What this means is that a class can expose a delegate to the outside world for event handling but restrict external entities from invoking (i.e., firing) the event.

Rate this Tip
To rate tips, you must be a member of SearchSOA.com.
Register now to start rating these tips. Log in if you are already a member.


Submit a Tip




DISCLAIMER: Our Tips Exchange is a forum for you to share technical advice and expertise with your peers and to learn from other enterprise IT professionals. TechTarget provides the infrastructure to facilitate this sharing of information. However, we cannot guarantee the accuracy or validity of the material submitted. You agree that your use of the Ask The Expert services and your reliance on any questions, answers, information or other materials received through this Web site is at your own risk.



SOA Trends and Strategy - SOA Education, SOA Development, SOA Implementations
About Us  |  Contact Us  |  For Advertisers  |  For Business Partners  |  Site Index  |  RSS
SEARCH 
TechTarget provides technology professionals with the information they need to perform their jobs - from developing strategy, to making cost-effective purchase decisions and managing their organizations' technology projects - with its network of technology-specific websites, events and online magazines.

TechTarget Corporate Web Site  |  Media Kits  |  Site Map




All Rights Reserved, Copyright 2001 - 2009, TechTarget | Read our Privacy Policy
  TechTarget - The IT Media ROI Experts