How can I restart a foreach
loop in C#??
For example:
Action a;
foreach(Constrain c in Constrains)
{
if(!c.Allows(a))
{
a.Change
for (var en = Constrains.GetEnumerator(); en.MoveNext(); )
{
var c = en.Current;
if (!c.Allows(a))
{
a.Change();
en = Constrains.GetEnumerator();
}
}
Use the good old goto
:
restart:
foreach(Constrain c in Constrains)
{
if(!c.Allows(a))
{
a.Change();
goto restart;
}
}
If you're diagnosed with gotophobia 100% of the time for some reason (which is not a good thing without a reason), you can try using a flag instead:
bool restart;
do {
restart = false;
foreach(Constrain c in Constrains)
{
if(!c.Allows(a))
{
a.Change();
restart = true;
break;
}
}
} while (restart);
void Main()
{
IEnumerable<Constrain> cons;
SomeObject a;
while(!TryChangeList(cons, a)) { }
}
// the name tryChangeList reveals the intent that the list will be changed
private bool TryChangeList(IEnumerable<Constrain> constrains, SomeObject a)
{
foreach(var con in constrains)
{
if(!c.Allows(a))
{
a.Change();
return false;
}
}
return true;
}
One way you can do that is using for, as you have already mentioned:
restart here is like continue or break but it restarts the foreach from the begining It is like setting the counter of a for loop to 0 again
Action a;
for(var index = 0; index < Constratins.Count; index++)
{
if(!Constraints[index].Allows(a))
{
a.Change();
index = -1; // restart
}
}
Although a very old thread - none of the answers paid due attention to the semantics of that code:
a
a
breaks any of them, try another a
and push that through the chain.That is, a.Change()
should be separated from the constraint checking loop, also adhering to the CQS principle:
while (!MeetsConstraints(a))
{
a.Change();
}
bool MeetsConstraints(Thing a)
{
return Constraints.All(c => c.Allows(a));
}
No goto, no ugly loops, just simple and clean. </self-back-slapping>