¿Cómo salgo de una lista .ForEach loop cuando uso un delegado anónimo?

En un bucle normal, puedes salir de un bucle usando break. ¿Se puede hacer lo mismo usando un delegado anónimo?

Ejemplo inputString y el resultado se declaran fuera del delegado.

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

Edit: Gracias por las respuestas, en realidad estoy leyendo su libro en el momento John 🙂 Solo para que quede constancia, resolví este problema y volví a un ciclo normal de foreach, pero publiqué esta pregunta para ver si me perdí algo.

Como otros han publicado, no puedes salir del bucle en ForEach.

¿Eres capaz de usar LINQ? Si es así, puede combinar fácilmente TakeWhile y un método de extensión ForEach personalizado (que casi todos los proyectos parecen tener en estos días).

Sin embargo, en su ejemplo, List.FindIndex sería la mejor alternativa, pero si en realidad no lo está haciendo, publique un ejemplo de lo que realmente quiere hacer.

No hay ningún bucle al que uno tiene acceso, desde el cual romper. Y cada llamada al delegado (anónimo) es una nueva llamada de función, por lo que las variables locales no ayudarán. Pero como C # le da un cierre, puede establecer una bandera y luego no hacer nada en llamadas posteriores:

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

(Esto debe probarse para verificar si se genera la semántica de referencia correcta para el cierre).

Un enfoque más avanzado sería crear su propio método de extensión que permitiera al delegado devolver falso para detener el bucle:

 static class MyExtensions { static void ForEachStoppable(this IEnumerable input, Func action) { foreach (T t in input) { if (!action(t)) { break; } } } } 

¿Tienes LINQ disponible para ti? Tu lógica parece similar a cualquiera:

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

que es lo mismo que

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

Si no tienes LINQ, esto sigue siendo lo mismo que:

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

Si desea ejecutar lógica adicional, hay cosas que puede hacer (con LINQ) con TakeWhile etc.

No creo que haya una forma elegante de hacerlo cuando se utiliza el método ForEach. Una solución hacky es lanzar una excepción.

¿Qué te impide hacer una antigua foreach?

 foreach (string item in blackList) { if (!inputString.Contains(item)) continue; result = true; break; } 

Si quieres un bucle, usa un bucle.

Action permite ningún valor de retorno, por lo que no hay forma de que la función ForEach pueda saber que desea interrumpir, sin lanzar una excepción. Usar una excepción aquí es una exageración.

La única forma de “salir” del bucle es lanzar una excepción. No existe una forma de “ruptura” para salir del método .ForEach como lo haría con un bucle foreach normal.

El método ForEach no es para hacer esto. Si desea saber si una colección contiene un elemento, debe utilizar el método Contains. Y si desea realizar una comprobación de todos los elementos de una colección, debe probar el método de extensión Cualquier.

  class Program { static void Main(string[] args) { List blackList = new List(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(this IEnumerable enumerable, Action action, Func breakOn) { foreach (var item in enumerable) { action(item); if (breakOn()) { break; } } } } 
 bool @break = false; blackList.ForEach(item => { if(!@break && inputString.Contains(item)) { @break = true; result = true; } if (@break) return; /* ... */ }); 

Tenga en cuenta que lo anterior todavía se repetirá a través de cada elemento, pero se devolverá de inmediato. Por supuesto, esta forma probablemente no sea tan buena como una persona normal.

Si realmente desea que exista un bucle foreach en una lista, puede usar la excepción como este código:

 public class ExitMyForEachListException : Exception { public ExitMyForEachListException(string message) : base(message) { } } class Program { static void Main(string[] args) { List str = new List() { "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(); } } 

Espero que esto ayude a obtener otro punto de vista.

Que este trabajo para usted:

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