由于 ForEach() 方法循环遍历所有列表成员,为什么不能使用break/continue子句,而我可以在正常的 foreach 循环中使用它们
lstTemp.ForEach(i=>
{
if (i == 3)
break;
//do sth
}
);
错误:
“没有可以中断或继续的封闭循环”
因为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
,因此你不能打破。
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 - 跳过。
大概是因为您使用的是 lambda 并且 lambda 的内容对它在循环中使用的事实一无所知。
而不是使用中断,首先执行一个过滤器(它可能不是您需要的确切过滤器,但说明了这一点)
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 是一种方法,而不是常规的 foreach 循环,所以需要使用常规的 foreach 循环遍历 lstTemp 以防中断,但如果继续在 ForEach 方法内使用 return。
var lstTemp = new List<int>() {1, 2, 3, 4};
lstTemp.ForEach(i=>
{
if (i == 3) return;
//do sth
Console.WriteLine(i);
});
输出:1、2、4
我解释它的方式是这样的:ForEach
是一种方法,而不是一种语言特征。C#foreach
构造是其他语言构造break
并被continue
允许使用的语言的特征。
我还要指出(不是试图判断,只是进行观察)这是一个很好的例子,说明了为什么一些开发人员反对使用一种ForEach
方法:在这种简单的情况下,它并没有真正节省打字,它需要更多重定向不是必要的,并且foreach
无论如何它都不具备所有功能。
在我看来,ForEach
方法有意义的主要场景是作为IEnumerable<T>
--to 的扩展,放在方法调用链的末尾。他们将其添加到List<T>
.
break 和 continue 是需要编译器支持的 C# 语言关键字。对于 C# 编译器来说,ForEach 只是一种方法。
因为您为列表中的每个项目委派了一个操作。
我用过
list.ForEach((item) =>
{
if( isBreak == false ) do
{
if (isContinue)
break;
// TODO
} while (false); }
});