una mostrar lista for elementos array agregar c# linq c#-3.0 ienumerable ilist

c# - mostrar - ¿Por qué es.ForEach() en IList<T> y no en IEnumerable<T>?



foreach list object c# (10)

ForEach se implementa en la clase concreta List<T>

Posible duplicado:
¿Por qué no hay un método de extensión ForEach en la interfaz IEnumerable?

Me he dado cuenta al escribir código LINQ-y que .ForEach () es un buen modismo para usar. Por ejemplo, aquí hay un fragmento de código que toma las siguientes entradas y produce estas salidas:

{ "One" } => "One" { "One", "Two" } => "One, Two" { "One", "Two", "Three", "Four" } => "One, Two, Three and Four";

Y el código:

private string InsertCommasAttempt(IEnumerable<string> words) { List<string> wordList = words.ToList(); StringBuilder sb = new StringBuilder(); var wordsAndSeparators = wordList.Select((string word, int pos) => { if (pos == 0) return new { Word = word, Leading = string.Empty }; if (pos == wordList.Count - 1) return new { Word = word, Leading = " and " }; return new { Word = word, Leading = ", " }; }); wordsAndSeparators.ToList().ForEach(v => sb.Append(v.Leading).Append(v.Word)); return sb.ToString(); }

Tenga en cuenta el .Instructo () antes del .ForEach () interpuesto en la penúltima línea.

¿Por qué es que .ForEach () no está disponible como un método de extensión en IEnumerable? Con un ejemplo como este, parece extraño.

Gracias por adelantado,

Dave


Honestamente, no sé con certeza por qué el .ForEach (Acción) no está incluido en IEnumerable pero, correcto, incorrecto o indiferente, así es como es ...

Sin embargo, QUISE destacar el problema de rendimiento mencionado en otros comentarios. Hay un golpe de rendimiento basado en cómo recorre una colección. Es relativamente menor pero, sin embargo, ciertamente existe. Aquí hay un fragmento de código increíblemente rápido y descuidado para mostrar las relaciones ... solo demora un minuto en ejecutarse.

class Program { static void Main(string[] args) { Console.WriteLine("Start Loop timing test: loading collection..."); List<int> l = new List<int>(); for (long i = 0; i < 60000000; i++) { l.Add(Convert.ToInt32(i)); } Console.WriteLine("Collection loaded with {0} elements: start timings",l.Count()); Console.WriteLine("/n<===============================================>/n"); Console.WriteLine("foreach loop test starting..."); DateTime start = DateTime.Now; //l.ForEach(x => l[x].ToString()); foreach (int x in l) l[x].ToString(); Console.WriteLine("foreach Loop Time for {0} elements = {1}", l.Count(), DateTime.Now - start); Console.WriteLine("/n<===============================================>/n"); Console.WriteLine("List.ForEach(x => x.action) loop test starting..."); start = DateTime.Now; l.ForEach(x => l[x].ToString()); Console.WriteLine("List.ForEach(x => x.action) Loop Time for {0} elements = {1}", l.Count(), DateTime.Now - start); Console.WriteLine("/n<===============================================>/n"); Console.WriteLine("for loop test starting..."); start = DateTime.Now; int count = l.Count(); for (int i = 0; i < count; i++) { l[i].ToString(); } Console.WriteLine("for Loop Time for {0} elements = {1}", l.Count(), DateTime.Now - start); Console.WriteLine("/n<===============================================>/n"); Console.WriteLine("/n/nPress Enter to continue..."); Console.ReadLine(); }

Sin embargo, no te obsesiones con esto demasiado. El rendimiento es la modernidad del diseño de la aplicación, pero a menos que la aplicación experimente un impacto real en el rendimiento que cause problemas de usabilidad, concéntrese en la codificación para su mantenimiento y reutilización, dado que el tiempo es la moneda de los proyectos empresariales de la vida real ...


LINQ sigue el modelo de extracción y todos sus métodos (de extensión) deben devolver IEnumerable<T> , excepto ToList() . ToList() está ahí para finalizar la cadena de extracción.

ForEach() es del mundo del modelo push.

Todavía puede escribir su propio método de extensión para hacer esto, como lo señala Samuel.


Para cada uno no está en IList está en la lista. Estabas usando la Lista concreta en tu ejemplo.


Porque ForEach(Action) existía antes de que existiera IEnumerable<T> .

Como no se agregó con los otros métodos de extensión, se puede suponer que los diseñadores de C # consideraron que era un mal diseño y prefieren la construcción foreach .

Editar:

Si lo desea, puede crear su propio método de extensión, no anulará el de una List<T> pero funcionará para cualquier otra clase que implemente IEnumerable<T> .

public static class IEnumerableExtensions { public static void ForEach<T>(this IEnumerable<T> source, Action<T> action) { foreach (T item in source) action(item); } }


Porque ForEach() en un IEnumerable es solo una normal para cada ciclo como este:

for each T item in MyEnumerable { // Action<T> goes here }


Según Eric Lippert, esto es principalmente por razones filosóficas . Deberías leer toda la publicación, pero esta es la esencia en lo que a mí respecta:

Me opongo filosóficamente a proporcionar ese método, por dos razones.

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 para 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 mucho a una expresión (aunque, ciertamente, dado que el método es inválido, 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 para sus efectos secundarios.

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


Solo estoy adivinando aquí, pero poner foreach en IEnumerable haría que las operaciones en él tuvieran efectos secundarios. Ninguno de los métodos de extensión "disponibles" causa efectos secundarios, por lo que poner un método imperativo como Foreach podría embarrar la API, supongo. Además, foreach inicializaría la colección perezosa.

Personalmente, he estado resistiendo la tentación de simplemente agregar el mío, solo para mantener las funciones libres de efectos secundarios separadas de las que tienen efectos secundarios.


Solo una suposición, pero List puede iterar sobre sus elementos sin crear un enumerador:

public void ForEach(Action<T> action) { if (action == null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match); } for (int i = 0; i < this._size; i++) { action(this._items[i]); } }

Esto puede conducir a un mejor rendimiento. Con IEnumerable, no tienes la opción de utilizar un ciclo for foráneo.


Se llama "Seleccionar" en IEnumerable<T> Estoy iluminado, gracias.