I have a list which is a bunch of functions as displayed below
var listOfSteps = new List<StepList>
{
new Setup(parameters),
new InitializeClass(parameters),
new calculate(parameters),
//72 steps in total
}
I have to add another function to the list based on a condition.
int result = select something from someTable
var listOfSteps = new List<StepList>
{
new Setup(parameters),
new InitializeClass(parameters),
new calculate(parameters),
if (result = 5) {new display(parameters)}, //This is the additional step to be added
//72 steps in total
}
I am trying to avoid creating 2 different sets for a simple if condition like below
if(result = 5)
{
var listOfSteps = new List<StepList> //list with the new function
{
new Setup(parameters),
new InitializeClass(parameters),
new calculate(parameters),
new display(parameters),
//72 steps in total
}
}
else
{ //list without the new function
new Setup(parameters),
new InitializeClass(parameters),
new calculate(parameters),
//72 steps in total
}
Is there a way to implement this condition within the list creation?
CodePudding user response:
I think it would be very readable if you can add a new kind of step - "do nothing":
// shouldn't StepList be renamed to "Step"?
class DoNothing: StepList {
...
// implement this so that when the list of steps is processed,
// this will do nothing
}
Then, you can use a simple ternary operator:
var listOfSteps = new List<StepList>
{
new Setup(parameters),
new InitializeClass(parameters),
new calculate(parameters),
result == 5 ?
new display(parameters)
:
new DoNothing(),
}
It would be even more readable if you can make factory methods for all your steps, so that you don't have the word new
all the time.
You can also use a switch expression:
var listOfSteps = new List<StepList>
{
new Setup(parameters),
new InitializeClass(parameters),
new calculate(parameters),
result switch {
5 => new display(parameters),
_ => new DoNothing(),
}
}
which would be very useful if you have more complicated decisions to make.
If the number of steps in the list of steps is important, you can always just remove the DoNothing
steps from the list with a Where
when you check the count.
listOfSteps.Where(step => step is not DoNothing).Count()
CodePudding user response:
I suppose that StepList
is a class which causes some operation to be performed when its object is encountered. The problem you are facing is that, depending on external condition, one StepList
object should be added or not, and that complicates List
initialization, right?
If that is the issue, then you may introduce a special "do nothing" StepList
subclass, e.g. called Empty
. Your list initialization would then look like this:
var listOfSteps = new List<StepList>
{
new Setup(parameters),
new InitializeClass(parameters),
new calculate(parameters),
(result == 5 ? new display(parameters) : new Empty())
// ... 72 steps in total
}
With this design, your list will always have the same number of items, but the result of their execution would depend on external condition.
CodePudding user response:
I would use a method with IEnumerable
as return type and do yield return
s where necessary.
eg.
private IEnumerable<StepList> GetSteps()
{
yield return new Setup(parameters);
yield return new InitializeClass(parameters);
yield return new calculate(parameters);
if (result = 5) yield return new display(parameters);
...
}
and than intialize the list like this:
var listOfSteps = GetSteps().ToList();
https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/yield
CodePudding user response:
Collection initializers are just syntactic sugar. Example:
var ints = new List<int> { 1, 2, 3 };
// is equivalent to
var temp = new List<int>();
temp.Add(1);
temp.Add(2);
temp.Add(3);
var ints = temp;
This means that you can simply add this new item conditionally afterwards:
var listOfSteps = new List<StepList>
{
new Setup(parameters),
new InitializeClass(parameters),
new calculate(parameters),
...
}
if (result == 5) {
listOfSteps.Add(new display(parameters));
}