La programmazione funzionale trova poco spazio nello sviluppo tradizionale a cui un programmatore .net, a meno che utizzi F#, e’ abituato. Nonostante cio’, la storia vuole che con gli ultimi rilasci del framework, in particolar modo con l’introduzione delle lambda expressions, e’ possibile scrivere tonnellate di codice affascinante (ed illegibile) da invogliare il vostro compagno di banco a cambiare lavoro. Tutto ruota intorna al concetto di delegate, termine preso in prestito da altri linguaggi per poi essere inflazionato in C#. La definizione piu’ semplice di delegate lo vuole come un “puntatore a funzione”. Una funzione diventa un oggetto vero proprio e la sua referenza (delegate) puo’ ad esempio essere passata come argomento ad un altro metodo o diventare il membro di una classe. Nel suo ambito originario creare una referenza ad un metodo e’ un’operazione semplice ed elegante, in .Net appare leggermente piu’ complicato e prolisso, e tutto cio’ che e’ prolisso distoglie l’attenzione dall’obbiettivo. Ci sono pero’ alcuni casi in cui il ricorso alla programmazione funzionale puo’ essere utile, si pensi all’inizializzazione di una classe tramite funzioni, a tecniche di lazy evaluation in cui un oggetto, per quando inizializzato con un metodo restituira’ il risultato di quest’ultimo solo quando necessario. Di seguito un paio di esempi :
Estendere un metodo passandolo come argomento ad un secondo metodo:
1: using System;
2: using System.Collections.Generic;
3: using System.Collections;
4: using System.Collections.Specialized;
5: using System.Linq;
6: using System.Text;
7:
8: namespace George.GenericFunc.ConsoleApp
9: {
10: class Program
11: {
12: static void Main(string[] args)
13: {
14: Func<bool> pointer = ConsoleNotifier.PrintOnScreen<string>(delegate() { return "Print me!"; });
15: pointer();
16: }
17: }
18:
19:
20: public class ConsoleNotifier
21: {
22: public static Func<bool> PrintOnScreen<T>(Func<T> externalFunction)
23: {
24: return new Func<bool>(delegate()
25: {
26: Console.WriteLine(externalFunction());
27: Console.ReadLine();
28: return true;
29: });
30: }
31: }
32:
33: }
Lazy:
1: using System;
2: using System.Collections.Generic;
3: using System.Collections;
4: using System.Collections.Specialized;
5: using System.Linq;
6: using System.Text;
7:
8: namespace George.GenericFunc.ConsoleApp
9: {
10: class Program
11: {
12: static void Main(string[] args)
13: {
14: Func<int, int> func1 = delegate(int x) { return x * x; };
15: int res = func1.Invoke(10); //not lazy
16: Func<int> refFunc = func1.Sample(10); // lazy
17: refFunc();
18: }
19: }
20:
21:
22: public static class MyExtensions
23: {
24: public static Func<Z> Sample<T, Z>(this Func<T, Z> func, T t)
25: {
26: return delegate() { return func(t); };
27: }
28:
29: }
30:
31: }