How do i exit a List.ForEach loop when usi

2019-02-05 12:15发布

In a normal loop you can break out of a loop using break. Can the same be done using an anonymous delegate?

Example inputString and result are both declared outside the delegate.

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.

11条回答
Evening l夕情丶
2楼-- · 2019-02-05 12:41

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:

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:

static class MyExtensions {
  static void ForEachStoppable<T>(this IEnumerable<T> input, Func<T, bool> action) {
    foreach (T t in input) {
      if (!action(t)) {
        break;
      }
    }
  }
}
查看更多
【Aperson】
3楼-- · 2019-02-05 12:45

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.

查看更多
家丑人穷心不美
4楼-- · 2019-02-05 12:48

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.

查看更多
我欲成王,谁敢阻挡
5楼-- · 2019-02-05 12:52

if you realy want to exist a loop foreach in a list you could use the exception like this code:

public class ExitMyForEachListException : Exception
{
    public ExitMyForEachListException(string message)
        : base(message)
    {
    }
}
class Program
{
    static void Main(string[] args)
    {
        List<string> str = new List<string>() { "Name1", "name2", "name3", "name4", "name5", "name6", "name7" };
        try
        {
            str.ForEach(z =>
            {
                if (z.EndsWith("6"))
                    throw new ExitMyForEachListException("I get Out because I found name number 6!");
                System.Console.WriteLine(z);
            });
        }
        catch (ExitMyForEachListException ex)
        {
            System.Console.WriteLine(ex.Message);
        }

        System.Console.Read();
    }
}

hope this help to get other point of view.

查看更多
叼着烟拽天下
6楼-- · 2019-02-05 12:57

Do you have LINQ available to you? Your logic seems similar to 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:

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

查看更多
女痞
7楼-- · 2019-02-05 12:57

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.

查看更多
登录 后发表回答