Delegate
I delegate sono un tipo di riferimento che rappresenta un metodo, trattarli come dati e quindi assegnarli ad una variabile o passarli come argomento ad un’altro metodo. Esempio di definizione di un delegate, notiamo che non ha un corpo :
Supponiamo di voler creare un delegate che riceve un intero e restituisce una stringa, utilizziamo un metodo che lo incapsula:
A questo punto possiamo istanziarlo:
Ora possiamo invocarlo semplicemente:
Oppure usarlo come parametro di un metodo:
Un delegate può mantenere al suo interno più riferimenti a diversi metodi, questo è utile per scrivere codice che possa notificare più oggetti invocando di ognuno un metodo.
Invocando il delegate i metodi verranno eseguiti nell’ordine di inserimento.
Per aggiungere un delegate possiamo utilizzare gli operatori + e +=, se invece vogliamo rimuoverlo utilizziamo gli operatori – e -=. L’aggiunta o la rimozione crea un nuovo delegate, i parametri in ingresso possono subire delle modifche ma il metodo successivo utilizza sempre il valore iniziale tranne che usiamo il modificatore ref e quindi il valore modificato da un metodo viene passato al metodo successivo. In un delegate multicast il parametro in uscita utilizzabile è solo l’ultimo gli altri verranno ignorati.
Il passo successivo sono i delegate generici, ecco un esempio
Possiamo utilizzarlo ad esempio in due versioni differenti:
delegate generici Func
Accettano un massimo di 16 parametri e restituiscono un risultato. Supponiamo di scrivereun metodo per il calcolo del fattoriale
Scriviamo un metodo generico di calcolo che utilizza il delegate Func
Possiamo utilizzare il metodo generico evaluate per calcolare il fattoriale nel seguente modo
Possiamo utilizzare lo stesso metodo Evaluate per il calcolo della radice quadrata
delegate generici Action
Semplicemente accetta parametri in ingresso, esegue un’azione ma non restituisce nessun valore.
Ad esempio ForEach(Action<T>) esegue un’azione, se T e’ una lista List<T> l’azione viene eseguita su tutti gli elementi della lista.
Vi è un particolare delegate Predicate<T>, valuta i criteri sull’argomento passato e restituisce un valore booleano. Ad esempio
Se Predicate è un metodo che verifica se un numero della lista è pari possiamo selezionare da una lista di numeri solo quelli pari. Quando il metodo è utilizzato solo dentro il delegate possiamo evitare di creare un metodo ma inserirlo in linea con il delegate, questo esempio estrae solo i numeri pari
Le espressioni lambda vengono spesso usate per istanziare un delegate, la forma è la seguente:
Supponiamo che vogliamo calcolare la media di due numeri e un’Action che legge un numero e lo visualizza possiamo semplicemente scrivere
Vediamo ora come utilizzare i delegate nella gestione degli eventi.
Gli eventi consentono ad un oggetto (publisher) di avvisare altri oggetti (subscriber) che si è verificato qualcosa, il publisher non sa quali subscriber saranno i consumatori dell’evento. Il delegate funge da intermediario fra le due parti.
La prima cosa da fare è una classe event che conterrà le informazioni relative all’evento, come esempio definiamo un evento quando il motore si spegne
Ora bisogna definire quando generare l’evento e avvisare altri oggetti interessati all’evento
Infine bisogna notificare che un oggetto è interessato all’evento e cosa fare quando viene generato
Supponiamo ora di voler passare al metodo che gestisce l’evento alcune informazioni, ad esempio il numero di giri raggiunto
Scriviamo l’evento MotoreFuoriGiri che deve visualizzare il numero di giri raggiunto
Quando non interessa più gestire l’evento basta rimuoverlo dalla lista