列出每个中断

发布于 2024-09-08 06:36:27 字数 389 浏览 9 评论 0原文

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

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

编辑:从问题注释中删除了“linq”,


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

is there a way to break out of the foreach extension method? The "break" keyword doesn't recognize the extension method as a valid scope to break from.

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

Edit: removed "linq" from question


note the code is just an example to show break not working in the extension method... really what I want is for the user to be able to abort processing a list.. the UI thread has an abort variable and the for loop just breaks when the user hits a cancel button. Right now, I have a normal for loop, but I wanted to see if it was possible to do with the extension method.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

痴者 2024-09-15 06:36:27

将其称为 List Foreach 与 LINQ Foreach 可能更准确。

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

创建具有中断功能的 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;}
    });

It's probably more accurate to call this a List<T> Foreach vs. a LINQ one.

In either case though no there is no way to break out of this loop. Primarily because it's not actually a loop per say. It's a method which takes a delegate that is called inside a loop.

Creating a ForEach with break capability is fairly straight forward though

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;
        }
    }
}

You could then rewrite your code as the following

Enumerable.Range(0,10)
    .ForEach((int i,ref bool doBreak) => {
        System.Windows.MessageBox.Show(i.ToString()); 
        if ( i > 2) {doBreak = true;}
    });
等风来 2024-09-15 06:36:27

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

I recommend using TakeWhile.

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

Or, using Rx:

Enumerable.Range(0, 10).TakeWhile(i => i <= 2).Run(i => MessageBox.Show(i.ToString()));
执着的年纪 2024-09-15 06:36:27

为什么不使用Where

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

Why not use Where?

Enumerable.Range(0, 10).Where(i => i <= 2).ToList().ForEach(...)
月亮邮递员 2024-09-15 06:36:27

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

尝试:

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

Try a "return" statement instead of "break"; it's a delegate function and not a real loop.

Try:

Enumerable.Range(0, 10).ToList().ForEach(i => { System.Windows.MessageBox.Show(i.ToString()); if (i > 2) return; });
姐不稀罕 2024-09-15 06:36:27

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

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

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

希望有帮助!

For myself, I used Linq Select + FirstOrDefault. Transform "each" in the list but since we are asking for the First, it will stop transforming them after finding the first one that matches.

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

As you can see I'm transforming each thing into an Option and my method AsThingOption may succeed at transforming and when it does we stop iterating over the list. If the conditions inside AsThingOption method never succeed at transforming, then end result is None.

Hope that helps!

浅笑依然 2024-09-15 06:36:27

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

Why not throw new Exception("Specific message") or use a boolean flag?

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;
}
猫九 2024-09-15 06:36:27

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

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

I have a case where I need to loop actions until a condition is false and each action can modify the value used to track the condition. I came up with this variation of .TakeWhile(). The advantage here is that each item in the list can participate in some logic, then the loop can be aborted on a condition not directly related to the item.

new List<Action> {
    Func1,
    Func2
}.TakeWhile(action => {
    action();
    return _canContinue;
});
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文