ForEach(): Почему нельзя использовать break/continue внутри

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

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

Ошибка:

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

Ответы

Ответ 1

Потому что 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, поэтому вы не можете сломать.

Ответ 2

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

Ответ 3

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

lstTemp.Where(i => i!= 3).ForEach(i=> // do sth);

Ответ 4

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

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

   //do stuff

   return false;
 }
);

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

Ответ 5

Как я объясню это: ForEach - это метод, а не язык. Конструкция С# ForEach является отличительной чертой языка, на котором допускаются конструкции другого языка break и continue.

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

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

Ответ 6

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 - пропущено.

Ответ 7

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

Ответ 8

Поскольку ForEach - это метод, а не регулярный цикл foreach, необходимо перебирать lstTemp с регулярным циклом foreach в случае разрыва, но в случае продолжения использования возврата внутри метода 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

Ответ 9

Поскольку вы делегируете действие для каждого элемента в списке.

Ответ 10

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

Ответ 11

я использовал его

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

                // TODO
            } while (false); }
        });