Click here to Skip to main content
15,867,141 members
Articles / Programming Languages / C#
Tip/Trick

Delegates Are Good, and Good For You

Rate me:
Please Sign up or sign in to vote.
4.88/5 (21 votes)
29 Aug 2011CPOL3 min read 34.6K   22   12
Using a delegate could pull your butt out of the fire when you don't want to refactor code to add functionality.
Have you ever been in the situation where you have a considerable base of existing code, and you need to add functionality, but you simply don't have the time to refactor all of the code to explicitly support the desired functionality? I'm sure anyone here with more than a few years of experience can answer "yes" to that question.

Today, I was faced with just such a situation. I'm working on a Silverlight app that displays a page on a button press. This page displays one of dozens of available views (depending on the button that caused the page to be displayed), and each view contains a collection of panels that display various data items. The panels can be manually expanded - or "zoomed" - by the user to consume the entire viewable area. The data for the panels may or may not be available, meaning that one or more of the panels would essentially be empty (or display a message saying no data is available). In that event, we want to automatically expand the panel that DOES contain data.

The best way (I think) to do this would be to change the constructor for the various chart views (there are several already implemented), but that could possibly cause problems with what is already expected, thus slowing development by everyone involved. I had to come up with a different solution, and the result is my tip.

I used a delegate. Delegates are kind of scarey for new programmers, but they're a godsend when you need a quick fix that doesn't require extensive changes to method/constructor parameter lists and such.

First, I came up with the method in my parent class:

public void ZoomPanelFromView(PanelType panel)
{
    // The methods called here already exist and are event handlers for when 
    // the user clicks one of the associated zoom buttons.
    switch (panel)
    {
        case PanelType.Main       : zMain_MouseLeftButtonUp(null, null); break;
        case PanelType.Ahead      : zAhead_MouseLeftButtonUp(null, null); break;
        case PanelType.AlibiTrend : zTrend_MouseLeftButtonUp(null, null); break;
    }
}


Next, I declared a globally accessible delegate that implemented the prototype for the method I was trying to "expose" from the parent class.

public delegate void PanelZoomer(PanelType panel);


Then, I declared a data member in a static class that I use for globally accessible methods and data members:

public class Globals
{
    // this delegate allows the chart classes to callback to the parent page and 
    // zoom the specified  panel
    public static PanelZoomer PanelZoom;

    public static Globals(){}
}


Now, with all of the pieces in place, I could set it in the parent class:

Globals.PanelZoom = this.ZoomPanelView;


...and use it from my view class that knows nothing of the parent page:

if (Globals.PanelZoom != null && m_dataPoints.Count == 0 && string.IsNullOrEmpty(m_data.textData))
{
    Globals.PanelZoom(PanelType.Main);
}


My solution didn't break anything, and requires no regression testing beyond making sure the user can still manually zoom the panels. Because I check for nullness on the delegate, I'm ensuring that the delegate has been set before using it. Everyone's happy, nobody has to change what they're doing or have already done with regards to the code already written, and we're free to add an overloaded constructor at our convenience. For the record, this is the only reason so far that the view class would have to know about the parent page at all, and IMHO, this doesn't warrant creating an overloaded constructor that allows the page to pass a pointer to itself to the view.

Yeah, I acknowledge that this breaks pretty much any OOP rule you might mention, and a band-aid like this is probably not the best solution, but the realities of working in a production environment are the biggest contributing factors of what you can and cannot implement when you're on a schedule.

I view OOP rules (and pretty much any other stuff you might consider to be a rule) as mere guidelines of things you SHOULD do, not what you MUST do. Finally, as long as your code is well documented (INCLUDING the *why-I-did-it" AND "where-I-did-it" behind the code), maintenance programmers can easily follow and modify your code without any problems at all.

There are a couple of additional tips here. Don't be rigid in your compliance with "industry standards", and be ready to look at a problem from different angles.

EDIT (29 Aug 2011) ================

Fixed some glaring typos.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Paddedwall Software
United States United States
I've been paid as a programmer since 1982 with experience in Pascal, and C++ (both self-taught), and began writing Windows programs in 1991 using Visual C++ and MFC. In the 2nd half of 2007, I started writing C# Windows Forms and ASP.Net applications, and have since done WPF, Silverlight, WCF, web services, and Windows services.

My weakest point is that my moments of clarity are too brief to hold a meaningful conversation that requires more than 30 seconds to complete. Thankfully, grunts of agreement are all that is required to conduct most discussions without committing to any particular belief system.

Comments and Discussions

 
GeneralWhy couldn't you have overloaded the constructor? The origi... Pin
Steve Roberson6-Sep-11 9:53
Steve Roberson6-Sep-11 9:53 
GeneralReason for my vote of 5 Good article with clear explaination... Pin
All Time Programming5-Sep-11 21:28
All Time Programming5-Sep-11 21:28 
GeneralReason for my vote of 5 Good aricle John and i agree with yo... Pin
Kurniawan Prasetyo5-Sep-11 21:25
Kurniawan Prasetyo5-Sep-11 21:25 
GeneralReason for my vote of 5 Good article Pin
mandar13051-Sep-11 21:34
mandar13051-Sep-11 21:34 
GeneralReason for my vote of 5 Thanks, John. Pin
Dr.Walt Fair, PE29-Aug-11 13:51
professionalDr.Walt Fair, PE29-Aug-11 13:51 
GeneralReason for my vote of 5 Great use of delegates. When I first... Pin
DevAffair28-Aug-11 3:36
DevAffair28-Aug-11 3:36 
GeneralReason for my vote of 5 Good one john Pin
thatraja23-Dec-10 4:37
professionalthatraja23-Dec-10 4:37 
GeneralYou "suspect"? This is precisely one of the uses for delegat... Pin
#realJSOP16-Nov-10 10:15
mve#realJSOP16-Nov-10 10:15 
GeneralReason for my vote of 3 Delegates have their uses but I susp... Pin
dmjm-h16-Nov-10 5:10
dmjm-h16-Nov-10 5:10 
GeneralReason for my vote of 5 Thanks for sharing this tip. Pin
linuxjr11-Nov-10 11:40
professionallinuxjr11-Nov-10 11:40 
GeneralStatic Constructor Pin
AspDotNetDev29-Aug-11 13:12
protectorAspDotNetDev29-Aug-11 13:12 
GeneralTypos Pin
AspDotNetDev25-May-10 13:58
protectorAspDotNetDev25-May-10 13:58 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.