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); }
});