列出 ForEach 休息时间

Posted

技术标签:

【中文标题】列出 ForEach 休息时间【英文标题】:List ForEach break 【发布时间】:2010-06-29 23:40:54 【问题描述】:

有没有办法摆脱 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 线程有一个 abort 变量和 for当用户点击取消按钮时,循环就会中断。现在,我有一个正常的 for 循环,但我想看看是否可以使用扩展方法。

【问题讨论】:

How do i exit a List<string>.ForEach loop when using an anonymous delegate?的可能重复 【参考方案1】:

将其称为 List&lt;T&gt; 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;
    );

【讨论】:

【参考方案2】:

我推荐使用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()));

【讨论】:

【参考方案3】:

为什么不使用Where

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

【讨论】:

【参考方案4】:

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

试试:

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

【讨论】:

【参考方案5】:

为什么不使用 foreach ? ...

PS:开个玩笑,正如你所提到的,我理解尝试查看如何使用 Linq 执行此操作的想法(出于同样的原因在此处搜索)......现在出于生产代码中维护/准备就绪的原因,猜测一个简单的foreach 有时就足够了。

【讨论】:

【参考方案6】:

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

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

如您所见,我正在将每个事物转换为选项,并且我的方法 AsThingOption 可能会成功转换,当它成功时,我们会停止迭代列表。如果 AsThingOption 方法中的条件从未成功转换,则最终结果为 None。

希望有帮助!

【讨论】:

【参考方案7】:

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

【讨论】:

【参考方案8】:

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

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

【讨论】:

以上是关于列出 ForEach 休息时间的主要内容,如果未能解决你的问题,请参考以下文章

forEach 列出数组的每个元素:

XSLT1,Muenchian 分组,在 foreach 循环中列出分组节点

PowerShell 中的嵌套 ForEach()

同一列表中的多个 ForEach 与具有一个 ForEach 的多个列表

我希望模式以正确的 ID 打开,即在 foreach

JavaScript forEach() 方法