Nesting conditionals in loops - c#

Given the following code, is there a better way to structure this?
foreach(Thing item in SomeRandomList)
{
bool firstCondition = CalculateBool(item, someValue);
bool secondCondition = CalculateBool(item, someOtherValue);
//General things are done...
if(firstCondition || secondCondition)
{
//semi-specific things are done...
if(firstCondition)
{
//specific things are done...
}
else
{
//specific things are done...
}
}
}
Also, what if there are more conditions, i.e. 3:
foreach(Thing item in SomeRandomList)
{
bool firstCondition = CalculateBool(item, someValue);
bool secondCondition = CalculateBool(item, someOtherValue);
//imagine as many more as you want.
bool nthCondition = CalculateBool(item, lastOtherValue);
//General things are done...
if(firstCondition || secondCondition || nthCondition)
{
//semi-specific things are done...
if(firstCondition)
{
//specific things are done...
}
else if(secondCondition)
{
//specific things are done...
}
else
{
//specific things are done...
}
}
}

Yes: Polymorphism.
Derive Thing's from a common base (or define an Interface that all Thing's implement)
Failing that, move the conditional testing code into a method on Thing.

If you can do the semi-specific things after the specific ones, you could try this:
bool anyTrue = true;
if (firstCondition)
{
// Specific things
}
else if (secondCondition)
{
// Specific things
}
else
{
// Specific things
anyTrue = false;
}
if (anyTrue)
{
// Semi-specific things
}
I don't know if it's necessarily better, but it's different...
Alternatively, I'm not all up on C# 3.0 and the fancy new LINQ stuff, but if its expressive enough you could try something like (pseudo-code):
bool[] conditions =
{
CalculateBool(item, someValue),
CalculateBool(item, someOtherValue),
...
};
if (conditions.AnyTrue)
{
switch (conditions.IndexOfFirstTrueItem)
{
case 0:
// Specific things
break;
case 1:
// Specific things
break;
default:
// Specific things
break;
}
}

I'd use some LINQ to use an intermediate query to help reduce the logic in the loop:
// Get condition in the query.
var query =
from item in SomeRandomList
let condition1 = CalculateBool(item, someValue1)
let condition2 = CalculateBool(item, someValue2)
...
let conditionN = CalculateBool(item, someValueN)
where
condition1 || condition2 || ... || conditionN
select new { Item = item,
Condition1 = condition1, Condition1 = condition2, ...
ConditionN = conditionN };
foreach(var item in query)
{
//semi-specific things are done...
if(firstCondition)
{
//specific things are done...
}
else
{
//specific things are done...
}
}
Hopefully, this will reduce the amount of code in the loop tremendously.
It seems to me though that you have a sequence of values that are being passed to CalculateBool for each item in SomeRandomList. If that is the case, then you could easily generate a query which does a cross join and filter on that:
// Get all valid items across all values.
var query =
from item in SomeRandomList
from value in someValues
where CalculateBool(item, value)
select { Item = item, Value = value };
// Iterate and process.
foreach (var item in query)
{
// Use item.Item and item.Value.
// Specifically, use item.Value to perform a lookup
// in a map somewhere to determine the course of action
// instead of a giant switch statement.
}
This would work because your conditionals indicate that you would only have one value set for each item.

I like the approach of having a dictionary of Predicate<T> and their associated Actions. I answered a similar question here:
Coming out of the habit of writing ifs/elseifs for every possible condition
To modify it a bit for your question:
Dictionary<Predicate<Something>, Action> mappings = {{...}}
bool shouldDoAnything = mappings.Keys.Aggregate(true, (accum, condition) =>
accum || condition);
if (shouldDoAnything)
{
//do semi-specific things
foreach(DictionaryEntry<Predicate<Something>, Action> mapping in mappings)
{
if (mapping.Key(input))
{
mapping.Value(); //do specific things
break;
}
}
}

foreach(Thing item in SomeRandomList)
{
DoGeneralThings(); //pass in whatever your require to the method
if(FirstCondition(item, someValue))
{
DoThingsWhenAnyConditionIsTrue(); //pass in whatever your require to the method
DoSpecificThingsForFirstCondition(); //pass in whatever your require to the method
continue;
}
if(SecondCondition(item, someValue))
{
DoThingsWhenAnyConditionIsTrue(); //pass in whatever your require to the method
DoSpecificThingsForSecondCondition(); //pass in whatever your require to the method
continue;
}
}

I might have not been able to get the question right, we can only have 2 results, if function has return type bool not n results, unless it is Nullable<bool>, which could return null as well.
so
bool result = CalculateBool(item, someValue);
if(result) {}
else {}
will do it.
about managing large if / else combination ? One way is to use Switch statement, that could increase readability.
But in any case, a method should always have least possible decision paths, this is known as
cyclomatic complexity.
If this happens, split the code into more appropriate methods

Related

Is there a better way to do nothing in a if, else if, else sequence

I'm doing an if, else if, else sequence within a foreach loop. In one of the states I don't want do do anything. Looks kind of weird and i'm wondering if there is a better way to do this?
foreach (var item in collection)
{
if (item.Contains("some text"))
{
removeNext = true;
myList.Add(item);
}
else if (item.ToUpper().Contains("TEXT IN UPPER") | item.Contains("some other text"))
{
// do nada
}
else if (removeNext)
removeNext = false;
else
myList.Add(item);
}
You could reverse the condition and put the rest of the code inside.
Optionally, you could reverse the condition as well to get if (!removeNext), making the code a bit shorted and arguably more readable, but also makes the assignment removeNext = false potentially useless, since it can be false already (but that's a negligible penalty).
foreach (var item in collection)
{
if (item.Contains("some text"))
{
removeNext = true;
myList.Add(item);
}
else if (!(item.ToUpper().Contains("TEXT IN UPPER") | item.Contains("some other text")))
{
if (!removeNext)
myList.Add(item);
removeNext = false;
}
}
But personally, I think the 'flat', unnested if that you have is way easier to read, and the continue command with a little line of comment, would make it nice and clear that that block intentionally does not have any code, and why.
Another way to write that logic is to keep track if the current item is being removed. Then you can separate the logic that determines if the next item should be removed and the logic that determines if the current item is keep no matter what from the logic that actually decides if the current item is added to myList. This way your condition clearly indicates it's purpose is to not remove the current item.
foreach (var item in collection)
{
bool removeCurrent = removeNext;
removeNext = false;
if (item.Contains("some text"))
{
removeNext = true;
removeCurrent = false;
}
else if (item.ToUpper().Contains("TEXT IN UPPER") | item.Contains("some other text"))
{
removeCurrent = false;
}
if (!removeCurrent)
myList.Add(item);
}
Just to give another possibility, you can include all the logic in a Where statement and avoid the loop altogether. This takes advantage of the fact that an assignment returns the result of the assignment, which allows us to both set the removeNext variable and ensure that we include multiple "some text" items even if they're adjacent to each other in the collection.
Note that this idea is more just for fun rather than for real-world code, as it's hard to read and would be prone to errors if someone were to try to update it:
bool removeNext = false;
var myList = collection.Where(i =>
!(i.ToUpper().Contains("TEXT IN UPPER") || i.Contains("some other text")) &&
(!removeNext | (removeNext = i.Contains("some text"))));
Explanation
The condition before the && strips out all the text we definitely don't care about. This was basically my comment under your original question (and by itself would be a good solution to pre-filter your results). The second part of the && reads:
"Select the item if removeNext is false OR if the result of the assignment removeNext = i.Contains("some text") is true"
The | is key here, because even if removeNext is false, we still want to do the assignment in the second part.
We don't use the || operator because it's a short-circuiting operator, meaning that if the first part returns true it doesn't bother to evaluate the second part (normally we want this optimization), and the removeNext value would never change.

C# replacing huge if-else statement

let's say i have Item object witch mostly holds enum properties like this
public enum Shape
{
square = 1,
trangle = 2,
any = 3
}
public enum Color
{
blue = 1,
red = 2,
yellow = 3,
green = 4
}
public enum Material
{
glass = 1,
wood = 2,
metal = 3
}
public class Item
{
public Shape ItemShape { get; set; }
public Color ItemColor { get; set; }
public Material ItemMaterial { get; set; }
}
What am trying to do is depends of combination of whole three properties i need to do some action later;
I was thinking to use if-else combination like:
if(item.ItemShape == Shape.square && item.ItemColor == Color.blue && item.ItemMaterial == Material.glass)
{
//call Action1
}
else if(item.ItemShape == Shape.square && item.ItemColor == Color.blue && item.ItemMaterial == Material.wood)
{
// action2
}
......
Problem is that i have around 16 of combinations, so it will be huge if-else method to resolve what method should i call later.
Maybe is there any other way to replace if-else statements more readable code, design patter or something more efficient?
I was thinking to combine whole possible states as flag enum values, but not sure if i can create enum value from object property later.
I think your best bet would be to ceate a Dictionary that would map your values to methods.
Now there are several options what could be the key in your dictionary - see below.
Disclaimer
Please also note that a big if statement is only an issue, if it is spread / duplicated across the codebase, and changes frequently - putting things in a dictionary does not really reduce complexity. Having methods in a dictionary also changes the semantics of your code. The first question should be - am I changing the mappings at runtime? Should they really be dynamic?
Dictionary with key ValueTuple struct you could use syntax (Shape, Color, Material) - this is the easiest one. Please note - not the Tuple class, but ValueTuple struct.
Dictionary with key Item class itself, but then you would need to take care about proper equality comparison in Item. You could make Item a struct to get that for free (but with slower performance, that comes from equality comparisons in System.ValueType that uses reflection in general case), or leave it as a class (or struct) and implement IEquatable<Item>, Equals and GetHashCode.
Without proper equality comparison, your dictionary lookup will not work (as suggested by #ckuri)
Use ValueTuple without a dictionary to simply condense your code.
A variation of the State pattern where you have a shared interface / base class for your handler. Handler is a separate class that contains one action for a specific set of values, like AnyBlueGlassHandler : Handler. Each handler checks the If condition, and when true, runs the actions. You could then put the handlers in a List<T> and apply them for an item like handlers.Foreach(x=>x.Handle(item))
The code when Item is the key could look like:
public static class ItemExtensions
{
static Dictionary<Item, Action<Item>>
methods = new Dictionary<Item, Action<Item>>()
{
{ new Item(Shape.any, Color.blue, Material.glass), x=> { /*do something*/ } }
};
public static bool TryApply(this Item item)
{
if (methods.TryGetValue(item, out var action))
{
action(item);
return true;
}
return false;
}
}
the code when ValueTuple is the key could look like
public static class ItemExtensionsUsingValueTuple
{
static Dictionary<(Shape, Color, Material), Action<Item>>
methods = new Dictionary<(Shape, Color, Material), Action<Item>>()
{
{ (Shape.any, Color.blue, Material.glass), x=> { /*do something*/ } }
};
public static bool TryApply(this Item item)
{
if (methods.TryGetValue((item.ItemShape, item.ItemColor, item.ItemMaterial), out var action))
{
action(item);
return true;
}
return false;
}
}
a more condensed version of your code with ifs, could look like:
declare Key property on your Item class
public (Shape, Color, Material) Key => (ItemShape, ItemColor, ItemMaterial);
use more elegant if statement
if ( item.Key == (Shape.any, Color.blue, Material.glass)) { }
It sounds like you want some rule set to check an item against.
I think the simplest form to make this more readable, is to pass the item, the properties of the rule, and the action to a separate method:
public bool RunActionIf(Item item, Shape shape, Color color, Material material, Action action)
{
if(item.ItemShape == shape && item.ItemColor == color && item.ItemMaterial == material)
{
action();
return true;
}
return false;
}
public void RunAction(Item item)
{
var result =
RunActionIf(item, Shape.square, Color.blue, Material.glass, Action1) ||
RunActionIf(item, Shape.square, Color.blue, Material.wood, Action2) ||
/* Implement your whole table like this */;
if(!result)
{
throw new ArgumentException("No matching rule found", nameof(item));
}
}
The main advantage of that method is that it's shorter and with less 'overhead' in the declaration. You can easily see: shape X + color Y + material Z= that action.
Another advantage is that it's easier to implement certain exceptions, for instance by allowing one of the rule parameters to be null to indicate any color, or to use Color.any to support that, although I think it's confusing to have any in the enum with other colors... Anyway, I digress. The point is, if you want to implement that, you have to do that only in one place without having to copy it 16 times.
You could abstract this away a bit further by making such a rule a separate object, which you can put in a list or dictionary, but for a definition like this, it doesn't make it that much more readable, although it does add some benefits of testibility, as well as the possibility to add different kinds of rules, without messing up your clean list again.
Try Dictionary<T>, for instance:
static Dictionary<Tuple<Shape, Color, Material>, Action> s_Actions = new
Dictionary<Tuple<Shape, Color, Material>, Action>() {
{Tuple.Create(Shape.square, Color.blue, Material.glass), () => { ... } },
...
{Tuple.Create(Shape.any, Color.red, Material.metal), () => { ... } },
...
};
private static void RunAction(MyItem item) {
Action action;
// Either exact match or match with Any
if (!s_Actions.TryGetValue(Tuple.Create(item.ItemShape, item.ItemColor, item.ItemMaterial),
out action))
action = s_Actions.FirstOrDefault(pair => pair.Key.Item1 == Color.any &&
pair.Key.Item2 == item.ItemColor &&
pair.Key.Item3 == item.ItemMaterial)
// Execute action if it's found
if (action != null)
action();
}
void RunAction((Shape shape, Color color, Material material) item)
{
switch(item)
{
case var i1 when i1.color == Color.red && i1.shape == Shape.square:
case var i2 when i2.color == Color.blue:
// Do action...
break;
case var i1 when i1.shape == Shape.trangle && i1.material == Material.metal:
// Do action...
break;
default:
// Do action...
break;
}
}
This solution uses Value Tuples, but primarily uses C#7 pattern matching in switch statements.
I don't think it totally solves your problem cleanly, but I think the multi-line cases gives you extra readability over the if statement approach and it's easy to implement.

Combine two expressions using LINQ?

var EXPEarners =
from victor in ins.BattleParticipants
where victor.GetComponent<TotalEXP>() != null
select victor;
foreach (GameObject victor in EXPEarners)
{
victor.GetComponent<TotalEXP>().value += EXPGain;
}
I'm new to LINQ and I would like some help. Is there a way to combine these two blocks of code so I don't have to call GetComponent() twice? (I'm using Unity.) Perhaps introduce a temporary variable and use a foreach loop instead? But the whole purpose of using LINQ was to avoid the foreach.
Also, is there a way to inject methods in between the LINQ statements, like call a void method before I select the final result, in case I want to do something "in between?"
There are a number of ways you could do this, but one small alteration to your query would get you to a single call:
First, get rid of the null check and simply return a map of victor and component:
var EXPEarners =
from victor in ins.BattleParticipants
select new {
victor,
component = victor.GetComponent<TotalEXP>()
};
Then, loop over each pair, adding the experience points if the component isn't null:
foreach (var participant in EXPEarners)
{
// can do something with participant.victor here
if (participant.component != null)
participant.component.value += EXPGain;
}
You could of course shorten this code up quite a bit, but if you do need to do something in between, you have the opportunity.
You could try this alternative:
// Dosomething for every item in the list
ins.BattleParticipants.All(gameObject => Reward(gameObject, EXPGain));
Then you write a method to perform "Reward", which can be as complex as you like
static bool Reward(GameObject gameObject, int EXPGain)
{
TotalEXP exp = gameObject.GetComponent<TotalEXP>();
if (exp != null)
{
exp.value += EXPGain;
return true;
}
return false;
}
And if you want, you can chain these, so for example you can also call a "Bonus" for all those you rewarded (where Reward returned true)
// Reward all EXPGain in the list then give them a Bonus
ins.BattleParticipants.Where(gameObject => Reward(gameObject, EXPGain)).All(gameObject => Bonus(gameObject, BONGain));
Then you write a method to perform "Bonus"
static bool Bonus(GameObject gameObject, int BONGain)
{
SomeOther soc = gameObject.GetComponent<SomeOther>();
if (soc != null)
{
soc.value += BONGain;
return true;
}
return false;
}
If you only want to increment TotalEXP value and you don't use a retrived GameObject somewhere else you can use let and retrive the collection of TotalEXP:
var TotalEXPs =
from victor in ins.BattleParticipants
let component = victor.GetComponent<TotalEXP>()
where component != null
select component;
foreach (TotalEXP expin TotalEXPs)
{
exp.value += EXPGain;
}
Otherwise, you can see #Cᴏʀʏ answer where you can retrive GameObject and it TotalEXP
Try searching for the "let" statement on LINQ. Maybe it can help you.

Neat way to write loop that has special logic for the first item in a collection

Often I have to code a loop that needs a special case for the first item, the code never seems as clear as it should ideally be.
Short of a redesign of the C# language, what is the best way to code these loops?
// this is more code to read then I would like for such a common concept
// and it is to easy to forget to update "firstItem"
foreach (x in yyy)
{
if (firstItem)
{
firstItem = false;
// other code when first item
}
// normal processing code
}
// this code is even harder to understand
if (yyy.Length > 0)
{
//Process first item;
for (int i = 1; i < yyy.Length; i++)
{
// process the other items.
}
}
How about:
using (var erator = enumerable.GetEnumerator())
{
if (erator.MoveNext())
{
ProcessFirst(erator.Current);
//ProcessOther(erator.Current); // Include if appropriate.
while (erator.MoveNext())
ProcessOther(erator.Current);
}
}
You could turn that into an extension if you want:
public static void Do<T>(this IEnumerable<T> source,
Action<T> firstItemAction,
Action<T> otherItemAction)
{
// null-checks omitted
using (var erator = source.GetEnumerator())
{
if (!erator.MoveNext())
return;
firstItemAction(erator.Current);
while (erator.MoveNext())
otherItemAction(erator.Current);
}
}
You could try:
collection.first(x=>
{
//...
}).rest(x=>
{
//...
}).run();
first / rest would look like:
FirstPart<T> first<T>(this IEnumerable<T> c, Action<T> a)
{
return new FirstPart<T>(c, a);
}
FirstRest rest<T>(this FirstPart<T> fp, Action<T> a)
{
return new FirstRest(fp.Collection, fp.Action, a);
}
You would need to define classed FirstPart and FirstRest. FirstRest would need a run method like so (Collection, FirstAction, and RestAction are properties):
void run()
{
bool first = true;
foreach (var x in Collection)
{
if (first) {
FirstAction(x);
first = false;
}
else {
RestAction(x);
}
}
}
I'd be tempted to use a bit of linq
using System.Linq;
var theCollectionImWorkingOn = ...
var firstItem = theCollectionImWorkingOn.First();
firstItem.DoSomeWork();
foreach(var item in theCollectionImWorkingOn.Skip(1))
{
item.DoSomeOtherWork();
}
I use the first variable method all the time and it seems totally normal to me.
If you like that better you can use LINQ First() and Skip(1)
var firstItem = yyy.First();
// do the whatever on first item
foreach (var y in yyy.Skip(1))
{
// process the rest of the collection
}
The way you wrote it is probably the cleanest way it can be written. After all, there is logic specific to the first element, so it has to be represented somehow.
In cases like this I would just use a for loop like this:
for(int i = 0; i < yyy.Count; i++){
if(i == 0){
//special logic here
}
}
Using a for loop also would allow you to do something special in other cases like on the last item, on even items in the sequence, ..etc.
IMHO the most cleanest way is: try to avoid special cases for the first item. That may not work in every situation, of course, but "special cases" may indicate that your program logic is more complex than it needs to be.
By the way, I would not code
if (yyy.Length > 0)
{
for(int i = 1; i <yyy.Length; i++)
{
// ...
}
}
but instead
for(int i = 1; i <yyy.Length; i++)
{
// ...
}
(which is itself a simple example of how to avoid unnecessary dealing with a special case.)
Here's a slightly simpler extension method that does the job. This is a combination of KeithS's solution and my answer to a related Java question:
public static void ForEach<T>(this IEnumerable<T> elements,
Action<T> firstElementAction,
Action<T> standardAction)
{
var currentAction = firstElementAction;
foreach(T element in elements)
{
currentAction(element);
currentAction = standardAction;
}
}
Whilst I wouldn't personally do this, there is another way using enumerators, which alleviates the need for conditional logic. Something like this:
void Main()
{
var numbers = Enumerable.Range(1, 5);
IEnumerator num = numbers.GetEnumerator();
num.MoveNext();
ProcessFirstItem(num.Current); // First item
while(num.MoveNext()) // Iterate rest
{
Console.WriteLine(num.Current);
}
}
void ProcessFirstItem(object first)
{
Console.WriteLine("First is: " + first);
}
Sample output would be:
First is: 1
2
3
4
5
Another option I came up with is
enum ItemType
{
First,
Last,
Normal
}
list.Foreach(T item, ItemType itemType) =>
{
if (itemType == ItemType.First)
{
}
// rest of code
};
Writing the extension method is left as an exercise for the reader…
Also should two Boolean flags “IsFirst” and “IsLast” be used instead of ItemType enum, or ItemType be an object that has “IsFirst” and “IsLast” properties?
Both of those are perfectly acceptable algorithms for processing the first element differently, and there really isn't a different way to do it. If this pattern is repeated a lot, you could hide it behind an overload of ForEach():
public static void ForEach<T>(this IEnumerable<T> elements, Action<T> firstElementAction, Action<T> standardAction)
{
var firstItem = true;
foreach(T element in elements)
{
if(firstItem)
{
firstItem = false;
firstElementAction(element)
}
else
standardAction(element)
}
}
...
//usage
yyy.ForEach(t=>(other code when first item), t=>(normal processing code));
Linq makes it a little cleaner:
PerformActionOnFirstElement(yyy.FirstOrDefault());
yyy.Skip(1).ForEach(x=>(normal processing code));
My solution:
foreach (var x in yyy.Select((o, i) => new { Object = o, Index = i } )
{
if (x.Index == 0)
{
// First item logic
}
else
{
// Rest of items
}
}

List ForEach break

is there a way to break out of the foreach extension method? The "break" keyword doesn't recognize the extension method as a valid scope to break from.
//Doesn't compile
Enumerable.Range(0, 10).ToList().ForEach(i => { System.Windows.MessageBox.Show(i.ToString()); if (i > 2)break; });
Edit: removed "linq" from question
note the code is just an example to show break not working in the extension method... really what I want is for the user to be able to abort processing a list.. the UI thread has an abort variable and the for loop just breaks when the user hits a cancel button. Right now, I have a normal for loop, but I wanted to see if it was possible to do with the extension method.
It's probably more accurate to call this a List<T> Foreach vs. a LINQ one.
In either case though no there is no way to break out of this loop. Primarily because it's not actually a loop per say. It's a method which takes a delegate that is called inside a loop.
Creating a ForEach with break capability is fairly straight forward though
public delegate void ForEachAction<T>(T value, ref bool doBreak);
public static void ForEach<T>(this IEnumerable<T> enumerable, ForEachAction<T> action) {
var doBreak = false;
foreach (var cur in enumerable) {
action(cur, ref doBreak);
if (doBreak) {
break;
}
}
}
You could then rewrite your code as the following
Enumerable.Range(0,10)
.ForEach((int i,ref bool doBreak) => {
System.Windows.MessageBox.Show(i.ToString());
if ( i > 2) {doBreak = true;}
});
I recommend using TakeWhile.
Enumerable.Range(0, 10).TakeWhile(i => i <= 2).ToList().ForEach(i => MessageBox.Show(i.ToString()));
Or, using Rx:
Enumerable.Range(0, 10).TakeWhile(i => i <= 2).Run(i => MessageBox.Show(i.ToString()));
Why not use Where?
Enumerable.Range(0, 10).Where(i => i <= 2).ToList().ForEach(...)
Try a "return" statement instead of "break"; it's a delegate function and not a real loop.
Try:
Enumerable.Range(0, 10).ToList().ForEach(i => { System.Windows.MessageBox.Show(i.ToString()); if (i > 2) return; });
For myself, I used Linq Select + FirstOrDefault. Transform "each" in the list but since we are asking for the First, it will stop transforming them after finding the first one that matches.
var thingOption = list.Select(thing => AsThingOption(thing))
.FirstOrDefault(option => option.HasValue) ?? Option.None<MyThing>;
As you can see I'm transforming each thing into an Option and my method AsThingOption may succeed at transforming and when it does we stop iterating over the list. If the conditions inside AsThingOption method never succeed at transforming, then end result is None.
Hope that helps!
Why not throw new Exception("Specific message") or use a boolean flag?
DataTable dt = new DataTable();
bool error = false;
try
{
dt.AsEnumerable().ToList().ForEach(dr =>
{
if (dr["Col1"].ToString() == "")
{
error = true;
throw new Exception("Specific message");
}
else
// Do something
});
}
catch (Exception ex)
{
if (ex.Message == "Specific message" || error)
// do something
else
throw ex;
}
I have a case where I need to loop actions until a condition is false and each action can modify the value used to track the condition. I came up with this variation of .TakeWhile(). The advantage here is that each item in the list can participate in some logic, then the loop can be aborted on a condition not directly related to the item.
new List<Action> {
Func1,
Func2
}.TakeWhile(action => {
action();
return _canContinue;
});

Categories