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

Using C# 7's Local Function Feature for Multiple Sequential Exit Test Scenarios

Rate me:
Please Sign up or sign in to vote.
4.83/5 (5 votes)
2 Apr 2019CPOL1 min read 15.6K   1   19
Where a function requires execution in stages, and a check for an exit condition after/with each stage

Introduction

Mads Torgersen described the use of C# 7's Local Function feature as:

You want a helper function. You are only using it from within a single function, and it likely uses variables and type parameters that are in scope in that containing function. On the other hand, unlike a lambda you don't need it as a first class object, so you don't care to give it a delegate type and allocate an actual delegate object. Also you may want it to be recursive or generic, or to implement it as an iterator.

A recent article here by Florian Rappl, Modernize Your C# Code - Part II: Methods, shows one implementation of this flow-of-control pattern using the Local Function feature; this tip shows an implementation that, IMHO, is simpler, cleaner.

Rappl's code example:

C#
void LongFunction()
{
    void Cleanup()
    {
        // Define cleanup logic here
    }

    // ... many steps
    if (specialCondition)
    {
        // ...
        Cleanup();
        return;
    }

    // ... many steps
    if (specialCondition)
    {
        // ...
        Cleanup();
        return;
    }

    // ...many steps
    Cleanup();
}

An alternative:

C#
public void OuterFunction(int a, int b)
{
    void Innerfunction()
    {
        // ... many steps
        if (a > b)
        {
            // ...
            CleanUp();
        }

        // ... many steps
        if (a < b)
        {
            CleanUp();
        }
    }

    void CleanUp()
    {
        // Cleanup code
        return;
    }

    Innerfunction();
}

This code simplifies the tests, and the 'CleanUp function is never executed if not explicitly called; of course, you may want to have the 'CleanUp function always executed: that's a trivial change.

There is one aspect of this that may be a bit confusing to some: the use of 'return in the 'CleanUp function does appear to return to the inner function; and, on exit, one might assume that the inner function is going to get called again.

That does not happen: the 'return in the 'CleanUp function will exit the OuterFunction: single-step through it, and see for yourself.

Edit in response to 'Anker: in this example, the 'return statement in the 'CleanUp function exits the 'OuterFunction because there is no other executable code in the outer function. If you add code after the 'CleanUp function, it will be executed.

History

  • 2nd April, 2019: Initial version

License

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


Written By
Chief Technology Officer
Thailand Thailand
Human being, mortal, flawed.

Comments and Discussions

 
SuggestionViolates my KISS principle Pin
Bruce Greene3-Apr-19 11:17
Bruce Greene3-Apr-19 11:17 
GeneralRe: Violates my KISS principle Pin
BillWoodruff4-Apr-19 14:03
professionalBillWoodruff4-Apr-19 14:03 
GeneralRe: Violates my KISS principle Pin
#realJSOP5-Apr-19 1:34
mve#realJSOP5-Apr-19 1:34 
GeneralRe: Violates my KISS principle Pin
BillWoodruff5-Apr-19 2:30
professionalBillWoodruff5-Apr-19 2:30 
QuestionTry... Finally? Pin
chrisbray3-Apr-19 3:05
chrisbray3-Apr-19 3:05 
AnswerRe: Try... Finally? Pin
BillWoodruff4-Apr-19 14:10
professionalBillWoodruff4-Apr-19 14:10 
GeneralRe: Try... Finally? Pin
chrisbray5-Apr-19 1:23
chrisbray5-Apr-19 1:23 
Try...Finally will not directly handle any errors, as there is no catch. The errors will still be thrown, it is just that the final bit that you want to run anyway will always be run whether you get an error or not. To handle errors you would need to add a catch clause, and I didn't do that because it was not shown in the original.

The purpose of doing it my way was to reduce the amount of code and the number of calls to the Cleanup method - this way you remove a call to the method for every check you do, and you are still guaranteed that it will run whether or not the remaining checks run *and* regardless of whether or not they are successful.
GeneralRe: Try... Finally? Pin
BillWoodruff5-Apr-19 3:11
professionalBillWoodruff5-Apr-19 3:11 
GeneralRe: Try... Finally? Pin
chrisbray5-Apr-19 4:02
chrisbray5-Apr-19 4:02 
GeneralRe: Try... Finally? Pin
BillWoodruff5-Apr-19 4:08
professionalBillWoodruff5-Apr-19 4:08 
GeneralRe: Try... Finally? Pin
chrisbray5-Apr-19 4:15
chrisbray5-Apr-19 4:15 
QuestionOld tech :) Pin
#realJSOP3-Apr-19 1:12
mve#realJSOP3-Apr-19 1:12 
AnswerRe: Old tech :) Pin
gdemont3-Apr-19 1:34
gdemont3-Apr-19 1:34 
AnswerRe: Old tech :) Pin
BillWoodruff4-Apr-19 13:59
professionalBillWoodruff4-Apr-19 13:59 
GeneralRe: Old tech :) Pin
#realJSOP4-Apr-19 15:11
mve#realJSOP4-Apr-19 15:11 
GeneralRe: Old tech :) Pin
#realJSOP5-Apr-19 1:30
mve#realJSOP5-Apr-19 1:30 
Questionincorrect Pin
Rekna Anker2-Apr-19 20:02
Rekna Anker2-Apr-19 20:02 
AnswerRe: incorrect Pin
BillWoodruff2-Apr-19 22:08
professionalBillWoodruff2-Apr-19 22:08 
QuestionLike it : - ) Pin
Florian Rappl2-Apr-19 12:00
professionalFlorian Rappl2-Apr-19 12:00 

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.