Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return from parent method inside of Action<string>

Tags:

c#

delegates

I am working inside of a method that performs a series of validation checks and should any of those checks fail it calls an Action<string> to run some common rejection code. The set up is something similar to this:

public void ValidationMethod() {
    Action<string> rejectionRoutine = (rejectionDescription) => {
        // do something with the reject description
        // other common code
    };

    if (condition != requiredValue) {
        rejectionRoutine("Condition check failed");
        // I currently have to put `return` here following every failed check
    }

    // many more checks following this
}

In this system once one check has failed validation I have no need to validate the rest, I just want to run the common rejection code inside the Action and exit the method. Currently to do this I just return on the next line following a call to rejectionRoutine. I'm wondering if there's a way I can incorporate the ability to return or terminate execution of the parent method from inside the Action?

I know this is a bit nit-picky but I feel like it is better for extensibility further down the road if someone else needs to add additional validation checks (they won't have to concern themselves with putting return all over the place) as well as encapsulating the common behavior of ending execution inside of code that is supposed to be common to these cases.

like image 918
Jesse Carter Avatar asked May 14 '13 13:05

Jesse Carter


2 Answers

One way of cleaning the code up a bit would be to extrapolate all of the checks out into a collection:

Dictionary<Func<bool>, string> checks = new Dictionary<Func<bool>, string>()
{
    {()=> condition != requiredValue, "Condition check failed"},
    {()=> otherCondition != otherRequiredValue, "Other condition check failed"},
    {()=> thirdCondition != thirdRequiredValue, "Third condition check failed"},
};

If it's important for the checks to be run in a particular order (this code has an unpredictable order) then you'd want to use something like a List<Tuple<Func<bool>, string>> instead.

var checks = new List<Tuple<Func<bool>, string>>()
{
    Tuple.Create<Func<bool>, string>(()=> condition != requiredValue
        , "Condition check failed"),
    Tuple.Create<Func<bool>, string>(()=> otherCondition != otherRequiredValue
        , "Other condition check failed"),
    Tuple.Create<Func<bool>, string>(()=> thirdCondition != thirdRequiredValue
        , "Third condition check failed"),
};

You can then use LINQ to do the validation:

var failedCheck = checks.FirstOrDefault(check => check.Item1());
if (failedCheck != null)
    rejectionRoutine(failedCheck.Item2);
like image 198
Servy Avatar answered Nov 06 '22 10:11

Servy


It doesn't make any sense to return from the caller method inside a lambda expression.
(what if you call it after the method is finished running?)

Instead, you can change it to a Func<string, Whatever> and return its value:

return rejectionRoutine("Condition check failed");
like image 36
SLaks Avatar answered Nov 06 '22 12:11

SLaks