My Blog

Deferred Execution

by lupok on venerdì 15 febbraio 2013 17:22

Per esecuzione posticipata si intende che la valutazione di un'espressione viene ritardata finché il relativo valore realizzato non risulta effettivamente necessario. L'esecuzione posticipata può contribuire a migliorare notevolmente le prestazioni quando è necessario modificare grandi raccolte di dati, in particolare in programmi che contengono una serie di modifiche o query concatenate. Nel migliore dei casi l'esecuzione posticipata consente di eseguire un'unica iterazione nella raccolta di origine. 

L'esecuzione posticipata è supportata direttamente nel linguaggio C# tramite la parola chiave yield (sotto forma di istruzione yield-return) quando viene utilizzata all'interno di un blocco iteratore. Tale iteratore deve restituire una raccolta di tipo IEnumerator o IEnumerator (o un tipo derivato).

Nell'esempio mostrato sotto sono presenti due operazioni di ricerca su una lista di interi, uno con esecuzione differita e uno senza.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
namespace DeferredExecution
{
 
   static class Program
   {
      static void Main(string[] args)
      {
         Int32[] array = { 1, 2, 4, 5, 7, 8, 9 };
 
         Console.WriteLine("Ricerca senza esecuzione posticipata");
 
         IEnumerable<int> result1 = Search<int>(array, 8);
 
         Console.WriteLine("Stampa elementi trovati senza esecuzione differita");
 
         foreach (var num in result1)
            Console.WriteLine("Item: {0}", num);
         
         //--
 
         Console.WriteLine("\n\nRicerca con esecuzione posticipata");
 
         IEnumerable<int> result2 = SearchDeferred<int>(array, 8);
 
         result2.ToList();
 
         Console.WriteLine("Stampa elementi trovati con esecuzione differita");
 
         //--
 
         foreach (var num in result2)
            Console.WriteLine("Item: {0}", num);
 
         Console.WriteLine("\n\nPress ENTER to exit");
         Console.ReadLine();
 
      }
 
      // metodo che effettua la ricerca dell'elemento specificato all'interno ù
      // di un array senza esecuzione posticipata
      public static IEnumerable<T> Search<T>(this IEnumerable<T> array, T element)
      {
         List<T> list = new List<T>();
         foreach (T item in array)
         {
            if (item.Equals(element))
            {
               Console.WriteLine("Found item: {0}", element);
               list.Add(item);
            }
         }
         return list.ToArray();
      }
 
      // metodo che effettua la ricerca dell'elemento specificato all'interno 
      // di un array con esecuzione posticipata
      public static IEnumerable<T> SearchDeferred<T>(this IEnumerable<T> array, T element)
      {
         foreach (T item in array)
         {
            if (item.Equals(element))
            {
               Console.WriteLine("Found item: {0}", element);
               yield return item;
            }
         }
      }
   }
}

Il codice riportato sopra produce il seguente output da dove si deduce che con l'esecuzione differita la lista non viene creata sino al momento in cui non viene utilizzata: 

L'invocazione di alcuni metodi sul risultato ottenuto con esecuzione posticipata produce la cosidetta "materializzazione" (Materialization), questo perchè alcuni metodi per compiere il proprio compito non possono fare altro che scorrere tutta la lista vanificando i benefici dell'esecuzione posticipata. Uno di questi metodi è ad esempio "ToList()", infatti modificando l'esempio precedente nel modo mostrato sotto, non vi sono differenze tra le due esecuzioni:

         //--
 
         Console.WriteLine("\n\nRicerca con esecuzione posticipata");
 
         IEnumerable<int> result2 = SearchDeferred<int>(array, 8);
 
         result2.ToList();
 
         Console.WriteLine("Stampa elementi trovati con esecuzione differita");
 
         //--
L'esecuzione del codice modificato come descritto produce il medisimo risultato sia con esecuzione differita che senza: 

DeferredExecution.zip

Blogs Parent Separator My Blog
Author
lupok

My Blog

Tags