Alternative for two sequentially executed loops with identical ranges [closed]

Posted on

Problem

For the moment I’m executing my code as follows:

foreach (int data in dataList)
{
    PreProcess(data);
}
foreach (int data in dataList)
{
    Process(data);
}

First I have to loop over some data (from a list) and to do some pre-processing after which then I do have to loop again over the same data list and do some processing, but those loops have to be run one after another, and cannot be merged as follows…

foreach (int data in dataList)
{
    PreProcess(data);
    Process(data); // Cannot be run in the same loop with PreProcess(data);
}

…because PreProcess(data) and Process(data) are logging a lot of information which could be interlaced in case both are looping together.


The only alternative I’ve found will be using Linq, but still has the same duplicate ForEach:

dataList.ForEach(data => { PreProcess(data); });
dataList.ForEach(data => { Process(data); });

Is there any way to rewrite this in order to remove the redundancy for two loops with same range, but still looping sequentially first over PreProcess(data) and Process(data) afterwards?

Solution

You could also define something like

private void MyLoop<T>(Action<T> action, IEnumerable<T> dataList) 
{
    foreach (var data in dataList)
    {
        action(data);
    }
}

and use it

MyLoop(Process, dataList);

or using Action

Action<Action<int>> myLoop= action =>
{
    foreach (var data in dataList)
    {
        action(data);
    }
};

and use it like this

myLoop(Process);

First Class Collection

The First Class Collection is an idea of the Object Calisthenics.

Any class that contains a collection should contain no other member variables. Each collection gets wrapped in its own class, so now behaviors related to the collection have a home.

We can wrap dataList into its own class

class DataList 
{

    private List<int> list;

    // ...
}

Feature Envy

A method accesses the data of another object more than its own data.

Since the collection dataList could be wrapped into its own class and gets modified by PreProcess and Process you have an Feature Envy.

We could put the methods PreProcess and Process into the class DataList

class DataList 
{

    private List<Data> list;

    public void PreProcess() 
    {
         /* ... */     
    } 

    public void Process() 
    {
         /* ... */ 
    } 
}

Now when you call it from the outside you simple call the methods

dataList.PreProcess();
dataList.Process();

interface IActionStrategy
{
    void applyTo(RequiredDataType data);
}
// ...
foreach (IActionStrategy strategy in strategyQueue)
    foreach (RequiredDataType data in dataList)
        strategy.applyTo(data);

Each strategy have to implement common interface in order to do it.

Leave a Reply

Your email address will not be published. Required fields are marked *