列表ForEach休息

时间:2010-06-29 23:40:55

标签: c# foreach break

有没有办法打破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循环,但我想看看是否可以使用扩展方法。

8 个答案:

答案 0 :(得分:17)

List<T> Foreach称为LINQ版本可能更为准确。

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

虽然

创建具有中断功能的ForEach但相当简单
public delegate void ForEachAction<T>(T value, ref bool doBreak);
public static void ForEach<T>(this IEnumerable<T> enumerable, ForEachAction<T> 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;}
    });

答案 1 :(得分:11)

我建议使用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()));

答案 2 :(得分:3)

为什么不使用Where

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

答案 3 :(得分:1)

尝试使用“return”语句而不是“break”;它是一个委托函数,而不是一个真正的循环。

尝试:

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

答案 4 :(得分:0)

为什么不使用foreach? ......

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

答案 5 :(得分:0)

对于我自己,我使用了Linq Select + FirstOrDefault。变换&#34;每个&#34;在列表中但由于我们要求First,它会在找到第一个匹配后停止转换它们。

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

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

希望有所帮助!

答案 6 :(得分:0)

为什么不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;
}

答案 7 :(得分:0)

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

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