ForEach (): почему нельзя использовать break / continue внутри
поскольку метод ForEach() проходит через все члены списка, почему нельзя использовать перерыв/продолжение предложение, пока я могу использовать их внутри обычного цикла foreach
lstTemp.ForEach(i=>
{
if (i == 3)
break;
//do sth
}
);
ошибка:
" нет замкнутого цикла, из которого break или continue"
11 ответов
, потому что ForEach
- Это метод, а не обычный foreach
петли. The ForEach
метод существует для простых задач, Если вам нужно сломать или продолжить, просто повторите lstTemp
обычный foreach
петли.
как правило, ForEach
реализован следующим образом:
public static ForEach<T>(this IEnumerable<T> input, Action<T> action)
{
foreach(var i in input)
action(i);
}
поскольку это обычный вызов метода,action
ничего не знает о вложении foreach
, таким образом, вы не можете сломать.
предположительно, потому что вы используете лямбду, а содержимое лямбды не знает о том, что оно используется внутри цикла.
вместо того, чтобы использовать перерыв, сначала выполните фильтр (это может быть не тот фильтр, который вам нужен, Но иллюстрирует точку)
lstTemp.Where(i => i!= 3).ForEach(i=> // do sth);
для итерации только части элементов и эмуляции перерыва отлично, вы можете использовать FirstOrDefault
:
lstTemp.FirstOrDefault(i=>
{
if (i == 3)
return true;
//do stuff
return false;
}
);
для списка со 100000 элементами, Если 10-й элемент равен 3, он будет повторяться только 10 раз, используя Where
решение будет работать,но сначала повторите весь список.
Я бы объяснил это так:ForEach
Это метод, а не языка. C# foreach
construct является особенностью языка, в рамках которого другой язык строит break
и есть.
Я бы также указал (не пытаясь судить, просто делая замечание), что это хороший пример того, почему некоторые разработчики возражают против использования ForEach
метод: он действительно не сохраняет ввод в этом простом случае, это требуется еще одно перенаправление, чем необходимо, и оно не имеет всей функциональности foreach
в любом случае.
на мой взгляд основной сценарий, в котором ForEach
метод имеет смысл как расширение на IEnumerable<T>
--поставить в конце цепочки вызовов методов. Мне кажется (мне) немного странным, что они добавили его в List<T>
.
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 - пропущен.
break и continue-ключевые слова языка C#, требующие поддержки компилятора. ForEach для компилятора C# - это просто метод.
поскольку 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
вы можете написать метод расширения "ForEachWhile", который принимает Function<T, bool>
и останавливается при false.
я использовал его
list.ForEach((item) =>
{
if( isBreak == false ) do
{
if (isContinue)
break;
// TODO
} while (false); }
});