列表ForEachrest

有没有办法打破foreach扩展方法? “break”关键字无法将扩展方法识别为要中断的有效范围。

//Doesn't compile Enumerable.Range(0, 10).ToList().ForEach(i => { System.Windows.MessageBox.Show(i.ToString()); if (i > 2)break; }); 

编辑:从问题中删除“linq”


注意代码只是一个示例,显示break在扩展方法中不起作用…我真正想要的是让用户能够中止处理列表.. UI线程有一个中止变量而for循环只是中断当用户点击取消按钮时。 现在,我有一个正常的for循环,但我想看看是否可以使用扩展方法。

将它称为List Foreach与LINQ之一可能更准确。

在任何一种情况下,虽然没有办法打破这个循环。 主要是因为它实际上并不是一个循环。 这是一个接受在循环内调用的委托的方法。

尽管如此,创建具有中断function的ForEach非常简单

 public delegate void ForEachAction(T value, ref bool doBreak); public static void ForEach(this IEnumerable enumerable, ForEachAction action) { var doBreak = false; foreach (var cur in enumerable) { action(cur, ref doBreak); if (doBreak) { break; } } } 

然后,您可以按以下方式重写代码

 Enumerable.Range(0,10) .ForEach((int i,ref bool doBreak) => { System.Windows.MessageBox.Show(i.ToString()); if ( i > 2) {doBreak = true;} }); 

我建议使用TakeWhile 。

 Enumerable.Range(0, 10).TakeWhile(i => i <= 2).ToList().ForEach(i => MessageBox.Show(i.ToString())); 

或者,使用Rx :

 Enumerable.Range(0, 10).TakeWhile(i => i <= 2).Run(i => MessageBox.Show(i.ToString())); 

为什么不使用Where

 Enumerable.Range(0, 10).Where(i => i <= 2).ToList().ForEach(...) 

尝试“返回”语句而不是“rest”; 它是委托函数而不是真正的循环。

尝试:

 Enumerable.Range(0, 10).ToList().ForEach(i => { System.Windows.MessageBox.Show(i.ToString()); if (i > 2) return; }); 

为什么不使用foreach ? …

PS:开个玩笑,正如你所提到的,我理解试图看看如何用Linq做这个想法(并且出于同样的原因用Google搜索)…现在出于生产代码中的维护/准备原因猜测一个简单的foreach是好的足够有时。

对于我自己,我使用了Linq Select + FirstOrDefault。 转换列表中的“each”,但由于我们要求First,它会在找到匹配的第一个后停止转换它们。

 var thingOption = list.Select(thing => AsThingOption(thing)) .FirstOrDefault(option => option.HasValue) ?? Option.None; 

正如您所看到的那样,我正在将每个事物转换为一个Option,而我的方法AsThingOption可能会成功转换,当它发生时我们会停止迭代列表。 如果AsThingOption方法中的条件永远不会成功转换,则最终结果为None。

希望有所帮助!

为什么不throw new Exception("Specific message")或使用布尔标志?

 DataTable dt = new DataTable(); bool error = false; try { dt.AsEnumerable().ToList().ForEach(dr => { if (dr["Col1"].ToString() == "") { error = true; throw new Exception("Specific message"); } else // Do something }); } catch (Exception ex) { if (ex.Message == "Specific message" || error) // do something else throw ex; } 

我有一个案例,我需要循环操作,直到条件为假,每个操作可以修改用于跟踪条件的值。 我想出了.TakeWhile()的这个变种。 这里的优点是列表中的每个项目都可以参与某些逻辑,然后循环可以在与项目不直接相关的条件下中止。

 new List { Func1, Func2 }.TakeWhile(action => { action(); return _canContinue; });