Joe Capka
Joe Capka

Reputation: 562

Strange control flow

I'm working on a framework in C# that will depend on pluggable components implemented as classes inheriting a base class. In order to make the components as simple as possible, I am working on some weird control flow.

The base class includes a static method RunStep(parameter). This method is called a number of times by the inheriting class, and each time it is called a condition is checked. If this condition happens to be false, I want the calling method to stop and return. A simplified working version of the code would be:

Base class:

class MyBase
{
  private static object RunStep(string parameter)
  {
    if(SomeFunction(parameter))
       return SomeOtherFunction(parameter);
    else
       return null;
  }  
}

Inheriting class:

class MyInheritor
{
  public void Run()
  {
     object result = RunStep("mystring1");
     if(null != result)
     {
        //perform some logic on result
        result = RunStep("mystring2");
        if(null != result){
            //perform some different logic on result
            RunStep("mystring3");
        }
     }
  }
}

What I am wondering is whether it is possible to do something in the base class so that I can simplify the inheriting class to this:

class MyInheritor2
{
  public void Run()
  {
     object result = RunStep("mystring1");
     //perform some logic on result
     result = RunStep("mystring2");
     //perform some different logic on result
     result = RunStep("mystring3");
     }
  }
}

I would put the parameters in a list and loop over them, but there is logic that needs to happen after each call to the RunStep method, and the logic is different each time. This takes a loop off the table. Also note that the logic between the RunStep calls accesses properties on result, so it crashes without the null checks.

It may seem like a trivial thing, but there may be thousands of these Inheriting classes and simplifying them is a big deal.

Upvotes: 3

Views: 220

Answers (2)

Dennis
Dennis

Reputation: 37770

Let the base class to control the execution flow:

class Base
{
    private readonly List<Tuple<string, Action>> steps = new List<Tuple<string, Action>>();

    protected void RegisterStep(string parameter, Action someLogic)
    {
        steps.Add(Tuple.Create(parameter, someLogic));
    }

    protected void Run()
    {
        foreach (var step in steps)
        {
            var result = RunStep(step.Item1);

            if (result == null)
            {
                break;
            }

            // perform some logic
            step.Item2();
        }
    }

    private object RunStep(string parameter)
    {
        // some implementation
        return null;
    }
}

class Derived : Base
{
    public Derived()
    {
        RegisterStep("1", () => { });
        RegisterStep("2", () => { });
        RegisterStep("3", () => { });

        // etc
    }
}

Upvotes: 3

Bobson
Bobson

Reputation: 13706

There's no way to make a function call exit the calling function except for throwing an Exception, which you shouldn't do.

What you can do to make your code cleaner is to invert the cases.

 object result = RunStep("mystring1");
 if (result == null) return;

 result = RunStep("mystring2");
 if (result == null) return;

 result = RunStep("mystring3");
 if (result == null) return;

Upvotes: 2

Related Questions