C# 使用匿名委托时如何退出 List<string>.ForEach 循环?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/557159/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do i exit a List<string>.ForEach loop when using an anonymous delegate?
提问by SecretDeveloper
In a normal loop you can break out of a loop using break. Can the same be done using an anonymous delegate?
在正常循环中,您可以使用 break 跳出循环。可以使用匿名委托来完成同样的事情吗?
Example inputString and result are both declared outside the delegate.
示例 inputString 和 result 都在委托之外声明。
blackList.ForEach(new Action<string>(
delegate(string item)
{
if(inputString.Contains(item)==true)
{
result = true;
// I want to break here
}
}
));
Edit: Thanks for the replies, I'm actually reading your book at the minute John :) Just for the record i hit this issue and switched back to a normal foreach loop but I posted this question to see if i missed something.
编辑:感谢您的回复,我实际上正在阅读您的书,约翰 :) 只是为了记录,我遇到了这个问题并切换回正常的 foreach 循环,但我发布了这个问题,看看我是否遗漏了什么。
采纳答案by Jon Skeet
As others have posted, you can't exit the loop in ForEach.
正如其他人发布的那样,您无法退出 ForEach 中的循环。
Are you able to use LINQ? If so, you could easily combine TakeWhile and a custom ForEach extension method (which just about every project seems to have these days).
你能使用 LINQ 吗?如果是这样,您可以轻松地将 TakeWhile 和自定义 ForEach 扩展方法结合起来(现在几乎每个项目似乎都有)。
In your example, however, List<T>.FindIndex
would be the best alternative - but if you're not actually doing that, please post an example of what you reallywant to do.
但是,在您的示例中,List<T>.FindIndex
将是最好的选择 - 但如果您实际上并没有这样做,请发布一个您真正想做的示例。
回答by JaredPar
The only way to "exit" the loop is to throw an exception. There is no "break" style way of exiting the .ForEach method like you would a normal foreach loop.
“退出”循环的唯一方法是抛出异常。没有像普通 foreach 循环那样退出 .ForEach 方法的“中断”样式方式。
回答by Michael Meadows
I don't think there's an elegant way to do it when using the ForEach method. A hacky solution is to throw an exception.
我认为在使用 ForEach 方法时没有一种优雅的方法可以做到这一点。一个hacky的解决方案是抛出一个异常。
What's preventing you from doing an old fashioned foreach?
是什么阻止你做一个老式的 foreach?
foreach (string item in blackList)
{
if (!inputString.Contains(item)) continue;
result = true;
break;
}
回答by Yuliy
If you want a loop, use a loop.
如果你想要一个循环,使用一个循环。
Action
allows for no return value, so there's no way the ForEach function could possibly know that you want to break, short of throwing an exception. Using an exception here is overkill.
Action
允许没有返回值,因此 ForEach 函数不可能知道您想要中断,除非抛出异常。在这里使用异常是矫枉过正的。
回答by Rune Grimstad
The ForEach method is not mean to do this. If you want to know if a collection contains an item you should use the Contains method. And if you want to perform a check on all items in a collection you should try the Any extention method.
ForEach 方法并不是要这样做。如果你想知道一个集合是否包含一个项目,你应该使用 Contains 方法。如果您想对集合中的所有项目执行检查,您应该尝试使用 Any 扩展方法。
回答by Richard
There is no loop that one has access to, from which to break. And each call to the (anonymous) delegate is a new function call so local variables will not help. But since C# gives you a closure, you can set a flag and then do nothing in further calls:
没有可以访问的循环,可以从中中断。对(匿名)委托的每次调用都是一个新的函数调用,因此局部变量将无济于事。但是由于 C# 给了你一个闭包,你可以设置一个标志,然后在进一步的调用中什么都不做:
bool stop = false;
myList.ForEach((a) => {
if (stop) {
return;
} else if (a.SomeCondition()) {
stop = true;
}
});
(This needs to be tested to check if correct reference semantics for closure is generated.)
(这需要测试以检查是否生成了正确的闭包引用语义。)
A more advanced approach would be to create your own extension method that allowed the delegate to return false to stop the loop:
更高级的方法是创建自己的扩展方法,允许委托返回 false 以停止循环:
static class MyExtensions {
static void ForEachStoppable<T>(this IEnumerable<T> input, Func<T, bool> action) {
foreach (T t in input) {
if (!action(t)) {
break;
}
}
}
}
回答by Marc Gravell
Do you have LINQ available to you? Your logic seems similar to Any:
你有可用的 LINQ 吗?您的逻辑似乎与 Any 类似:
bool any = blackList.Any(s=>inputString.Contains(s));
which is the same as:
这与:
bool any = blackList.Any(inputString.Contains);
If you don't have LINQ, then this is still the same as:
如果您没有 LINQ,那么这仍然与以下内容相同:
bool any = blackList.Find(inputString.Contains) != null;
If you want to run additional logic, there are things you can do (with LINQ) with TakeWhile
etc
如果你想运行额外的逻辑,你可以做一些事情(使用 LINQ)TakeWhile
等等
回答by Jaime Febres
class Program
{
static void Main(string[] args)
{
List<string> blackList = new List<string>(new[] { "jaime", "jhon", "febres", "velez" });
string inputString = "febres";
bool result = false;
blackList.ForEach((item) =>
{
Console.WriteLine("Executing");
if (inputString.Contains(item))
{
result = true;
Console.WriteLine("Founded!");
}
},
() => result);
Console.WriteLine(result);
Console.ReadLine();
}
}
public static class MyExtensions
{
public static void ForEach<T>(this IEnumerable<T> enumerable, Action<T> action, Func<bool> breakOn)
{
foreach (var item in enumerable)
{
action(item);
if (breakOn())
{
break;
}
}
}
}
回答by Mark Cidade
bool @break = false;
blackList.ForEach(item =>
{
if(!@break && inputString.Contains(item))
{ @break = true;
result = true;
}
if (@break) return;
/* ... */
});
Note that the above will still iterate through each item but return immediately. Of course, this way is probably not as good as a normal foreach
.
请注意,上述内容仍将遍历每个项目,但会立即返回。当然,这种方式恐怕不如普通方式foreach
。
回答by Andrew Mochalskyy
Would this work for you:
这对你有用吗:
bool result = null != blackList.Find( item => inputString.Contains(item)) );