Click here to Skip to main content
Click here to Skip to main content

Tagged as

Go to top

Hide Ad-hoc Methods Inside the Calling Method’s Body

, 21 Dec 2010
Rate this:
Please Sign up or sign in to vote.
Using anonymous methods helps to limit visibility of code callable just from within one method
Why would anyone restrict any code visibility and scope inside an assembly? Well, by the same reasons limited variable scope is used. The users of Pascal and Delphi (major predecessor of .NET) miss its local methods -- local to the scope of some other method. However, this feature is actually available with .NET and C#.
 
Let's consider the following code:
 
void AdjustMargins(FrameworkElement frameworkElement) {
    Thickness margin = frameworkElement.Margin;
    Control parent = frameworkElement.Parent as FrameworkElement;
    if (parent == null) return;
    if (parent.Margin.Left > 0) margin.Left = 0;
    if (parent.Margin.Right > 0) margin.Right = 0;
    if (parent.Margin.Top > 0) margin.Left = 0;
    if (parent.Margin.Bottom > 0) margin.Bottom = 0;
    //..
    frameworkElement.Margin = margin;
} //AdjustMargins

void AdjustLayout() {
    AdjustMargins(panelTop);
    AdjustMargins(panelButtons);
    AdjustMargins(panelProperties);
    AdjustMargins(panelOutput);
    //..
} //AdjustLayout
 
It does not really matter what it does. What's wrong in this code?
 
The major reason method AdjustMargins code is created as a separate method is elementary code reuse because it is called from the body of the method AdjustLayout more than once. At the same time, this sample suggests that AdjustMargins is an ad-hoc method called only from AdjustLayout. So, this code is just fine, but it could be a bit more manageable if the callable code of AdjustMargins could be placed entirely into the scope and made completely invisible outside of this scope.
 
If the Window class being developed is small enough, it does not matter, but what if it is already overwhelmed with other methods (or tends to be overwhelmed later down the road)? In this case, reducing number of methods visible at the level of the class really helps to keep this class manageable.
 
This is where local methods would help a bit, but there is no such thing in .NET -- with the exclusion of anonymous method. With the anonymous methods, one could achieve the same effect as with local methods. We need to use the following pattern:
 
void AdjustLayout() {
    System.Action<FrameworkElement> adjustMargins =
        (FrameworkElement frameworkElement) => {
        Thickness margin = frameworkElement.Margin;
        Control parent = frameworkElement.Parent as FrameworkElement;
        if (parent == null) return;
        if (parent.Margin.Left > 0) margin.Left = 0;
        if (parent.Margin.Right > 0) margin.Right = 0;
        if (parent.Margin.Top > 0) margin.Left = 0;
        if (parent.Margin.Bottom > 0) margin.Bottom = 0;
        //...
        frameworkElement.Margin = margin;
    }; //adjustMargins
    adjustMargins(panelTop);
    adjustMargins(panelButtons);
    adjustMargins(panelProperties);
    adjustMargins(panelOutput);
    //...
} //AdjustLayout
 
What if some code should be local but shared by two or more calling methods? Well, delegates are first-class objects, so they can be passed as parameters. Here is a more complex example:
 
void AdjustLayout() {
    System.Action<FrameworkElement> adjustMargins =
        (FrameworkElement frameworkElement) => {
        Thickness margin = frameworkElement.Margin;
        Control parent = frameworkElement.Parent as FrameworkElement;
        if (parent == null) return;
        if (parent.Margin.Left > 0) margin.Left = 0;
        if (parent.Margin.Right > 0) margin.Right = 0;
        if (parent.Margin.Top > 0) margin.Left = 0;
        if (parent.Margin.Bottom > 0) margin.Bottom = 0;
        //...
        frameworkElement.Margin = margin;
    }; //adjustMargins
    System.Action<FrameworkElement,
    System.Action<FrameworkElement>>
        adjustCombined =
        (FrameworkElement frameworkElement, 
        System.Action<FrameworkElement> adjustMarginsMethod) => {
        if (adjustMarginsMethod != null)
            adjustMarginsMethod(frameworkElement);
        //other adjustments...
    };
    foreach (var element in new FrameworkElement[] {
        panelTop,
        panelButtons, panelProperties, })
        adjustMargins(element);
    adjustMargins(panelOutput);
    adjustCombined(panelOutput, adjustMargins);
    //...
} //AdjustLayout

License

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

Share

About the Author

Sergey Alexandrovich Kryukov
Architect
United States United States
No Biography provided

Comments and Discussions

 
QuestionIs it really worth that? PinmemberSergeyT228-Dec-10 12:11 
AnswerRe: Is it really worth that? PinmemberSAKryukov28-Dec-10 17:38 

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

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

| Advertise | Privacy | Mobile
Web04 | 2.8.140916.1 | Last Updated 21 Dec 2010
Article Copyright 2010 by Sergey Alexandrovich Kryukov
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid