关于c#:ForEach():为什么不能在内部使用break / continue

ForEach() : Why can't use break/continue inside

由于ForEach()方法遍历所有列表成员,所以为什么不能使用break / continue子句,而我却可以在正常的foreach循环中使用它们

1
2
3
4
5
6
7
lstTemp.ForEach(i=>
 {
   if (i == 3)
   break;
   //do sth
 }
);

错误:

"No enclosing loop out of which to
break or continue"


因为ForEach是方法而不是常规的ForEach循环。如果需要中断或继续执行ForEach方法,只需使用常规的ForEach循环遍历lstTemp

通常,ForEach是这样实现的:

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

因为它是一个普通的方法调用,所以action对封闭的ForEach一无所知,因此您不会中断。


大概是因为您使用的是lambda,而lambda的内容对于在循环内使用的事实一无所知。


returnForEach中将充当continue

例:

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

打印1、2、4。

3-跳过。


与其先休息,不如先做一个过滤器(它可能不是您需要的确切过滤器,但说明了要点)

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


要仅迭代部分项并完美模拟中断,可以使用FirstOrDefault

1
2
3
4
5
6
7
8
9
10
lstTemp.FirstOrDefault(i=>
 {
   if (i == 3)
       return true;

   //do stuff

   return false;
 }
);

对于包含100000个项目的列表,如果第10个项目为3,它将仅迭代10次,使用Where解决方案将起作用,但首先迭代整个列表。


我的解释方式是:ForEach是一种方法,而不是语言功能。 C#ForEach构造是该语言的功能,允许使用其他语言构造breakcontinue

我还要指出(不做判断,只是做一个观察),这是一个很好的例子,说明为什么某些开发人员反对使用ForEach方法:在这种简单情况下,它并没有真正节省输入,需要比必要多一个重定向,并且它不具备ForEach的所有功能。

在我看来,ForEach方法有意义的主要场景是对IEnumerable< T >的扩展-放在方法调用链的末尾。他们将它添加到List< T >中似乎对我来说有点奇怪。


因为ForEach是一种方法,因此不是常规的foreach循环,需要在常规的foreach循环中遍历lstTemp进行迭代,以防发生中断,但是如果继续,请在ForEach方法内使用return。

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

输出:1、2、4


中断和继续是需要编译器支持的C#语言关键字。对于C#编译器来说,ForEach只是一种方法。


您可以编写扩展方法" ForEachWhile",该方法采用Function并且在为false时停止。


因为您为列表中的每个项目委派了一个动作。


我用了

1
2
3
4
5
6
7
8
9
10
        list.ForEach((item) =>
        {
            if( isBreak == false ) do
            {
                if (isContinue)
                    break;

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