Domanda

  

Possibile duplicato:
   Equivalente LINQ di foreach per IEnumerable < T >

I metodi di estensione linq per ienumerable sono molto utili ... ma non molto utili se tutto ciò che vuoi fare è applicare un calcolo a ciascun elemento dell'enumerazione senza restituire nulla. Quindi mi chiedevo se forse mi mancava solo il metodo giusto o se davvero non esiste poiché preferirei utilizzare una versione integrata se è disponibile ... ma non ne ho trovata una: -)

Avrei potuto giurare che ci fosse un metodo .ForEach da qualche parte, ma devo ancora trovarlo. Nel frattempo, ho scritto la mia versione nel caso fosse utile a chiunque altro:

using System.Collections;
using System.Collections.Generic;

public delegate void Function<T>(T item);
public delegate void Function(object item);

public static class EnumerableExtensions
{
    public static void For(this IEnumerable enumerable, Function func)
    {
        foreach (object item in enumerable)
        {
            func(item);
        }
    }

    public static void For<T>(this IEnumerable<T> enumerable, Function<T> func)
    {
        foreach (T item in enumerable)
        {
            func(item);
        }
    }
}

l'utilizzo è:

myEnumerable.For<MyClass>(delegate(MyClass item) { item.Count++; });

È stato utile?

Soluzione

Spargendo un po 'più di luce sul perché:

LINQ è di natura funzionale. Viene utilizzato per eseguire query sui dati e restituire risultati. Una query LINQ non dovrebbe alterare lo stato dell'applicazione (con alcune eccezioni come la memorizzazione nella cache). Poiché foreach non restituisce alcun risultato, non ha molti usi che non implicano l'alterazione dello stato di qualcosa oltre a quello che ci stai passando. E se hai bisogno di un metodo di estensione Foreach (), è facile da implementare.

Se, d'altra parte, quello che vuoi è prendere input e chiamare una funzione su ogni elemento che restituisce un risultato, LINQ fornisce un modo attraverso il suo metodo di selezione.

Ad esempio, il codice seguente chiama un delegato di funzione su ogni elemento in un elenco, restituendo vero se quell'elemento è positivo:

    static void Main(string[] args)
    {
        IEnumerable<int> list = new List<int>() { -5, 3, -2, 1, 2, -7 };
        IEnumerable<bool> isPositiveList = list.Select<int, bool>(i => i > 0);

        foreach (bool isPositive in isPositiveList)
        {
            Console.WriteLine(isPositive);
        }

        Console.ReadKey();        
    }

Altri suggerimenti

In realtà, il framework delle estensioni reattive di Microsoft Research ha aggiunto questa funzionalità. Nell'assemblea System.Interactive hanno incluso un Run() e un Do() estensioni a IEnumerable<T>.

Esegui (azione) eseguirà l'azione su ciascun elemento e la restituirà. Ciò è utile per aggiungere la registrazione a una query linq, ad esempio:

var res = GetRandomNumbers(100).Take(10)
      .Do(x => Console.WriteLine("Source  -> {0}", x))
      .Where(x => x % 2 == 0)
      .Do(x => Console.WriteLine("Where   -> {0}", x))
      .OrderBy(x => x)
      .Do(x => Console.WriteLine("OrderBy -> {0}", x))
      .Select(x => x + 1)
      .Do(x => Console.WriteLine("Select  -> {0}", x));

Ciò comporterà:

Source  -> 96 
Where   -> 96 
Source  -> 25 
Source  -> 8 
Where   -> 8 
Source  -> 79 
Source  -> 25 
Source  -> 3 
Source  -> 36 
Where   -> 36 
Source  -> 51 
Source  -> 53 
Source  -> 81 
OrderBy -> 8 
Select  -> 9 
9 
OrderBy -> 36 
Select  -> 37 
37 
OrderBy -> 96 
Select  -> 97 
97

Esegui (azione) è come un ciclo foreach, il che significa che piega la sequenza che esegue l'azione.

Puoi leggere di più qui: http://community.bartdesmet.net/blogs/bart/archive/2009/12/26/more-linq-with-system-interactive-the-ultimate-imperative. aspx

Il framework Rx è disponibile qui: http://msdn.microsoft. com / it-it / devlabs / ee794896.aspx

Il metodo ForEach su List<T> fa questo. Potresti racchiudere la tua raccolta in un elenco e quindi utilizzare quella chiamata, ma non è davvero una cosa carina da fare. Sembra che dovrai fare il tuo.

Già discusso qui e .

Sono troppo assonnato per ricordare ma, fondamentalmente, un metodo .ForEach in un'applicazione a thread singolo è funzionalmente equivalente all'istruzione foreach già esistente. Da quello che ho capito, la differenza principale è che un ForEach potrebbe essere parallelizzato ma che introdurrebbe comportamenti indesiderati troppo facilmente.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top