Saltar al contenido

¿Existe algún método como ForEach para IList?

Este equipo de especialistas pasados algunos días de trabajo y de juntar de datos, dimos con la respuesta, queremos que todo este artículo sea de gran utilidad para tu trabajo.

Solución:

Utilizar una foreach círculo:

foreach (var p in names) 
    Console.WriteLine(p);

No hay razón para usar delegados y métodos de extensión en todas partes si eso no mejora la legibilidad; a foreach bucle no es menos explícitamente decirle a los lectores lo que se está haciendo que un ForEach método.

Si tu IList es un array (T[]), entonces tienes el método Array.ForEach en ellos similar a ForEach sobre List. Puede crear un método de extensión para su personalizado IList o IEnumerable o lo que prefieras.

public static void ForEach(this IList list, Action action)

    foreach (T t in list)
        action(t);

Solo debe tener cuidado con el hecho de que los objetos de la colección original se modificarán, pero supongo que el nombre lo implica.

————————————————– ————————————————– ——————————–

Prefiero llamar:

people.Where(p => p.Tenure > 5)
      .Select(p => p.Nationality)
      .ForEach(n => AssignCitizenShip(n);

que

foreach (var n in people.Where(p => p.Tenure > 5).Select(p => p.Nationality))

    AssignCitizenShip(n);

Si es así, puede crear el método de extensión en IEnumerable. Cuidado con la llamada final ForEach ejecuta el Linq consulta. Si no lo desea, también puede aplazarlo utilizando yield declaración y devolviendo una IEnumerable espalda:

public static IEnumerable ForEach(this IEnumerable list, Action action)

    foreach (T t in list)
    
        action(t);
        yield return t;
    

Eso resuelve el problema de los efectos secundarios, pero personalmente me gusta un método llamado ForEach para finalmente ejecutar la llamada.

————————————————– ————————————————– ——————————-

Para abordar los puntos de vista opuestos sobre las preferencias, aquí hay un enlace mejor de Eric Lippert que este. Para citarlo:

“La primera razón es que hacerlo viola los principios de programación funcional en los que se basan todos los demás operadores de secuencia. Claramente, el único propósito de una llamada a este método es causar efectos secundarios. El propósito de una expresión es calcular un valor, no causar un efecto secundario. El propósito de una declaración es causar un efecto secundario. El sitio de llamada de esta cosa se parecería muchísimo a una expresión (aunque, es cierto, ya que el método es void-regresando, la expresión solo podría usarse en un contexto de “expresión de declaración”. No me sienta bien hacer el único operador de secuencia que solo es útil por sus efectos secundarios.

La segunda razón es que hacerlo agrega cero nuevo poder de representación al lenguaje “.

Eric no está diciendo que sea algo malo, solo el filosófico Razones detrás de la decisión de no incluir el constructo en Linq por defecto. Si cree una función en un IEnumerable no debe actuar sobre el contenido, entonces no lo haga. Personalmente no me importa, ya que soy muy consciente de lo que hace. Lo trato como cualquier otro método que cause efectos secundarios en una clase de colección. Puedo ingresar a la función y depurarla también si quiero. Aquí hay otro de Linq sí mismo.

people.Where(p => p.Tenure > 5)
      .Select(p => p.Nationality)
      .AsParallel()
      .ForAll(n => AssignCitizenShip(n);

Como diría, no hay nada malo en estos. Es solo una preferencia personal. No usaría esto para anidado foreachs o si involucra más de una línea de código para ejecutar dentro del foreach bucle ya que eso es ilegible. Pero por simple ejemplo que publiqué, me gusta. Parece limpio y conciso.

Editar: Ver un enlace de rendimiento por cierto: ¿Por qué List.ForEach más rápido que foreach estándar?

Podría crear un método de extensión y utilizar la mayor parte de la implementación de void List.ForEach(Action action). Puede descargar el código fuente en el sitio de Shared Source Initiative.

Básicamente terminarás con algo como esto:

public static void ForEach(this IList list, Action action) 

    if (list == null) throw new ArgumentNullException("null");
    if (action == null) throw new ArgumentNullException("action");

    for (int i = 0; i < list.Count; i++)
    
        action(list[i]);
    

Es ligeramente mejor que las otras implementaciones que utilizan la foreach declaración, ya que aprovecha el hecho de que IList incluye un indexador.

Aunque estoy de acuerdo con la respuesta de OR Mapper, a veces en grandes proyectos con muchos desarrolladores es difícil convencer a todos de que un foreach la declaración es más clara. Peor aún, si su API se basa en interfaces (IList) en lugar de tipos concretos (List), entonces los desarrolladores que están acostumbrados a List.ForEach method podría empezar a llamar ToList en sus referencias IList! Lo sé porque sucedió en mi proyecto anterior. Estaba usando las interfaces de colección en todas partes en nuestras API públicas siguiendo el Directrices de diseño del marco. Me tomó un tiempo darme cuenta de que muchos desarrolladores no estaban acostumbrados a esto y llamar a ToList comenzó a aprehender a un ritmo alarmante. Finalmente agregué este método de extensión a un ensamblado común que todos estaban usando y me aseguré de que todas las llamadas innecesarias a ToList fueron eliminados del código base.

Agradecemos que desees corroborar nuestra investigación mostrando un comentario o puntuándolo te damos las gracias.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *