recorrer for example array c# loops delegates

c# - example - ¿Cómo salgo de un bucle List<string>.ForEach cuando uso un delegado anónimo?



recorrer string foreach c# (11)

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

Ejemplo inputString y resultado son ambos declarados fuera del delegado.

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

Edit: gracias por las respuestas, en realidad estoy leyendo tu libro en el minuto John :) Solo para el registro toco este tema y volví a un ciclo foreach normal, pero publiqué esta pregunta para ver si me perdí algo.


¿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 tiene LINQ, este sigue siendo el mismo que:

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

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


Como otros publicaron, no puedes salir del ciclo en ForEach.

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

En su ejemplo, sin embargo, List<T>.FindIndex sería la mejor alternativa, pero si no está haciendo eso, publique un ejemplo de lo que realmente desea hacer.


El método ForEach no es malo para hacer esto. Si desea saber si una colección contiene un elemento, debe usar el método Contiene. Y si desea realizar un control de todos los elementos de una colección, debe probar el método de extensión Any.


La única forma de "salir" del bucle es lanzar una excepción. No existe una forma de estilo "break" de salir del método .ForEach como lo haría con un ciclo foreach normal.


No creo que haya una manera elegante de hacerlo cuando se usa el método ForEach. Una solución hacky es arrojar una excepción.

¿Qué te impide hacer un foreach pasado de moda?

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


No hay ningún bucle al que se tenga acceso, desde el cual se pueda romper. Y cada llamada al delegado (anónimo) es una nueva llamada a función para que las variables locales no ayuden. Pero como C # le da un cierre, puede establecer un indicador 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 una 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 ciclo:

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


Que este trabajo para usted:

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


Si quieres un bucle, usa un bucle.

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


si realmente quiere que exista un bucle foreach en una lista, podría 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<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(); } }

Espero que esta ayuda para obtener otro punto de vista.


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


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

Tenga en cuenta que lo anterior aún se repetirá a través de cada elemento, pero regresará inmediatamente. Por supuesto, esta forma probablemente no sea tan buena como un foreach normal.