Перезапустить цикл foreach в C #? - PullRequest
18 голосов
/ 01 января 2011

Как перезапустить цикл foreach в C # ??

Например:

Action a;
foreach(Constrain c in Constrains)
{
   if(!c.Allows(a))
   {
      a.Change();
      restart;
   }
}

restart здесь похоже на continue или break, но оно перезапускает foreach с самого начала Это все равно, что снова установить счетчик цикла for на 0 ..

Возможно ли это в C #?

Редактировать: Я хочу поблагодарить Мехрдада Афшари и Махеша Велагу за то, что они позволили мне обнаружить ошибку (index = 0) в моей текущей реализации, которая не была бы обнаружена иначе ..

Ответы [ 5 ]

58 голосов
/ 01 января 2011

Используйте старый добрый goto:

restart:
foreach(Constrain c in Constrains)
{
   if(!c.Allows(a))
   {
      a.Change();
      goto restart;
   }
}

Если по какой-либо причине у вас диагностирована гофобия в 100% случаев (что не хорошая вещь без причины), вы можете попробовать использовать вместо этого флаг:

bool restart;
do {
   restart = false;
   foreach(Constrain c in Constrains)
   {
      if(!c.Allows(a))
      {
         a.Change();
         restart = true;
         break;
      }
   }
} while (restart);
8 голосов
/ 27 мая 2014

Хотя это очень старая тема - ни один из ответов не обратил должного внимания на семантику этого кода:

  • У вас есть цепочка ограничений на a
  • Если a сломает любой из них, попробуйте другой a и протолкните его через цепь.

То есть a.Change() должен быть отделен от цикла проверки ограничений, также придерживаясь принципа CQS:

while (!MeetsConstraints(a))
{
    a.Change();
}

bool MeetsConstraints(Thing a)
{
    return Constraints.All(c => c.Allows(a));
}

Нет гото, нет уродливых петель, просто и чисто. </ Самообеспечение обратно пощечины>

8 голосов
/ 01 января 2011

Один из способов сделать это с помощью for, как вы уже упоминали:

перезапуск здесь аналогичен продолжению или разрыву, но он перезапускает foreach с началасчетчик цикла for для 0 снова

Action a;
for(var index = 0; index < Constratins.Count; index++)
{
   if(!Constraints[index].Allows(a))
   {
      a.Change();
      index = -1; // restart
   }
}
4 голосов
/ 01 января 2011
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;
}
0 голосов
/ 01 января 2011
for (var en = Constrains.GetEnumerator(); en.MoveNext(); )
{
    var c = en.Current;
    if (!c.Allows(a))
    {
        a.Change();
        en = Constrains.GetEnumerator();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...