ForEach (): почему нельзя использовать break / continue внутри - PullRequest
15 голосов
/ 14 декабря 2010

Поскольку метод ForEach () перебирает все члены списка, почему нельзя использовать предложение break / continue , тогда как я могу использовать их внутри обычного цикла foreach

lstTemp.ForEach(i=>
 {
   if (i == 3)
   break;
   //do sth
 }
);

Ошибка:

"Нет замкнутой петли, из которой перерыв или продолжение "

Ответы [ 11 ]

19 голосов
/ 14 декабря 2010

Потому что ForEach - это метод, а не обычный цикл foreach. Метод ForEach предназначен для простых задач, если вам нужно прервать или продолжить, просто переберите lstTemp с обычным циклом foreach.

Обычно ForEach реализован так:

public static ForEach<T>(this IEnumerable<T> input, Action<T> action)
{
  foreach(var i in input)
    action(i);
}

Поскольку это обычный вызов метода, action ничего не знает о включающем foreach, поэтому вы не можете его сломать.

17 голосов
/ 14 декабря 2010

Предположительно, потому что вы используете лямбду, а содержимое лямбды игнорирует тот факт, что используется внутри цикла.

10 голосов
/ 14 декабря 2010

вместо того, чтобы использовать разрыв, сначала выполните фильтр, подобный этому (он может быть не тем, который вам нужен, но иллюстрирует суть)

lstTemp.Where(i => i!= 3).ForEach(i=> // do sth);
6 голосов
/ 28 августа 2014

return будет действовать как continue в ForEach.

Пример:

var list = new List<int>() {1, 2, 3, 4};
list.ForEach(i => 
    {
        if (i == 3)
            return;
        Console.WriteLine(i);
    }
);

Печать 1, 2, 4.

3 - пропущено.

5 голосов
/ 14 декабря 2010

Чтобы перебрать только часть элементов и идеально имитировать разрыв, вы можете использовать FirstOrDefault:

lstTemp.FirstOrDefault(i=>
 {
   if (i == 3)
       return true;

   //do stuff

   return false;
 }
);

Для списка с 100000 элементов, если 10-й элемент равен 3, он будет повторяться только 10 раз, при этом будет работать решение Where, но сначала будет повторяться весь список.

4 голосов
/ 14 декабря 2010

Я бы объяснил это так: ForEach - это метод , а не языковая функция . Конструкция C # foreach - это особенность языка, на которой разрешены другие языковые конструкции break и continue.

Я также хотел бы отметить (не пытаясь судить, просто сделав наблюдение), что это хороший пример того, почему некоторые разработчики возражают против использования метода ForEach: он действительно не экономит при наборе текста в этой простой В этом случае требуется больше перенаправления, чем необходимо, и в любом случае он не обладает всеми функциями foreach.

По моему мнению, основной сценарий, в котором метод ForEach имеет смысл, заключается в расширении IEnumerable<T> - в конце цепочки вызовов метода. Мне кажется немного странным, что они добавили его в List<T>.

2 голосов
/ 14 декабря 2010

break и continue являются ключевыми словами языка C #, которые требуют поддержки компилятора.ForEach для компилятора C # - это просто метод.

1 голос
/ 06 сентября 2015

Поскольку ForEach является методом, а не обычным циклом foreach, необходимо выполнить итерацию по lstTemp с обычным циклом foreach в случае прерывания, но в случае продолжения используйте return внутри метода ForEach.

var lstTemp = new List<int>() {1, 2, 3, 4};
lstTemp.ForEach(i=>
{
     if (i == 3) return;
     //do sth
     Console.WriteLine(i);
});

Выход: 1, 2, 4

0 голосов
/ 24 октября 2013

Я использовал это

        list.ForEach((item) =>
        {
            if( isBreak == false ) do
            {
                if (isContinue)
                    break;

                // TODO
            } while (false); }
        });
0 голосов
/ 14 декабря 2010

Вы можете написать метод расширения «ForEachWhile», который принимает Function<T, bool> и останавливается при значении false.

...