如何在使用匿名委托时退出List <string> .ForEach循环?</string>

时间:2009-02-17 14:47:58

标签: c# loops delegates

在正常循环中,您可以使用break中断循环。可以使用匿名代理完成同样的工作吗?

实施例 inputString和result都在委托之外声明。

blackList.ForEach(new Action<string>(
    delegate(string item)
    {
        if(inputString.Contains(item)==true)
        {
            result = true;
            // I want to break here
        }
    }
));

编辑: 感谢回复,我实际上是在约翰那时读你的书:)为了记录,我点击这个问题并切换回正常的foreach循环,但我发布了这个问题,看看我是否错过了什么。

12 个答案:

答案 0 :(得分:37)

正如其他人发布的那样,你无法在ForEach中退出循环。

你能使用LINQ吗?如果是这样,您可以轻松地将TakeWhile和自定义ForEach扩展方法结合起来(几乎每个项目似乎都有这些日子)​​。

但是,在您的示例中,List<T>.FindIndex将是最佳选择 - 但如果您实际上没有这样做,请发布您 想要做的事情的示例。< / p>

答案 1 :(得分:27)

没有可以访问的循环,从中可以断开。每次调用(匿名)委托都是一个新的函数调用,因此局部变量无济于事。但是,由于C#给你一个闭包,你可以设置一个标志,然后在进一步的调用中什么都不做:

bool stop = false;
myList.ForEach((a) => {
  if (stop) {
    return;
  } else if (a.SomeCondition()) {
    stop = true;
  }
});

(需要对此进行测试以检查是否生成了关闭的正确引用语义。)

更高级的方法是创建自己的扩展方法,允许委托返回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;
      }
    }
  }
}

答案 2 :(得分:15)

你有LINQ可用吗?你的逻辑似乎与Any:

类似
bool any = blackList.Any(s=>inputString.Contains(s));

与:

相同
bool any = blackList.Any(inputString.Contains);

如果你没有LINQ,那么它仍然是:

bool any = blackList.Find(inputString.Contains) != null;

如果你想运行其他逻辑,你可以用TakeWhile等来做(使用LINQ)

答案 3 :(得分:6)

在使用ForEach方法时,我认为没有一种优雅的方法。一个hacky解决方案是抛出异常。

什么阻止你做一个老式的foreach?

foreach (string item in blackList)
{
    if (!inputString.Contains(item)) continue;

    result = true;
    break;
}

答案 4 :(得分:3)

如果你想要一个循环,请使用循环。

Action允许没有返回值,因此ForEach函数无法知道您想要中断,除非抛出异常。在这里使用例外是过度的。

答案 5 :(得分:2)

“退出”循环的唯一方法是抛出异常。没有“破解”方式退出.ForEach方法,就像普通的foreach循环一样。

答案 6 :(得分:2)

ForEach方法并不意味着这样做。如果您想知道集合是否包含项目,则应使用Contains方法。如果你想对集合中的所有项目进行检查,你应该尝试使用Any extention方法。

答案 7 :(得分:1)

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

答案 8 :(得分:1)

bool @break = false;

blackList.ForEach(item =>
 {  
    if(!@break && inputString.Contains(item))
     { @break = true;
       result = true;
     }

    if (@break) return;
    /* ... */
 });

请注意,上述内容仍将遍历每个项目,但会立即返回。当然,这种方式可能不如普通的 foreach 那么好。

答案 9 :(得分:1)

如果您真的希望在列表中存在循环foreach,则可以使用此代码中的异常:

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

希望这有助于获得其他观点。

答案 10 :(得分:0)

这对你有用吗?

bool result = null != blackList.Find( item => inputString.Contains(item)) );

答案 11 :(得分:-2)

blackList.ForEach(new Action<string>(
    delegate(string item)
    {
        if(inputString.Contains(item)==true)
        {
            result = true;
            // I want to break here
            return;
        }
    }
));