Immaginiamo di voler creare in C# una classe generica che possa gestire dei tipi aperti, un po’ come succede per le liste. Per esercizio vogliamo creare una classe chiamata Materie che accetti diverse classi come tipo di materia gestito, per esempio una classe Matematica. L’oggetto che vogliamo creare sarà di questo tipo:
1 |
Materie<Matematica> m = new Materie<Matematica>(); |
A questo punto vogliamo avere un metodo per aggiungere dei voti per gli studenti della data materia, nel modo seguente:
1 |
m.addVoto(new Matematica("Mario",10)); |
E infine vogliamo poter estrarre, dal nostro oggetto m, una media dei voti, passandogli una funzione che si occuperà di definire il meccanismo di estrazione del voto dall’oggetto generico sul tipo aperto.
Per cui creiamo anzitutto la classe Matematica:
1 2 3 4 5 6 7 8 9 10 11 |
class Matematica { public string corso; public int voto; public Matematica(string c, int v) { corso = c; voto = v; } } |
E poi creiamo la classe Materie:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
class Materie<T> { List<T> voti = new List<T>(); public void addVoto(T voto) { voti.Add(voto); } public double getMediaVoti(Func<T,double> funzioneMedia) { double media = 0; if( voti.Count > 0 ) { foreach (T voto in voti) { media += funzioneMedia(voto); } media /= voti.Count; } return media; } } |
Faccio notare che il metodo getMediaVoti accetta come argomento un metodo generico che prenda che abbia come argomento il tipo aperto T e come restituzione un double (supponiamo che volendo calcolare dei voti essi dovranno essere comunque ricondotti a double).
Uniamo il tutto nel modo seguente:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
class Program { static void Main(string[] args) { Materie<Matematica> m = new Materie<Matematica>(); m.addVoto(new Matematica("Mario",10)); m.addVoto(new Matematica("Luigi", 8)); m.addVoto(new Matematica("Luisa", 9)); double media = m.getMediaVoti(calcolaMedia); Console.WriteLine("media {0}",media); Console.ReadLine(); } static double calcolaMedia(Matematica m) { return m.voto; } } |
In questo caso l’oggetto m si comporta in modo analogo ad una lista, permettendo l’aggiunta di n elementi del tipo T, nel nostro caso Matematica. Dal momento che noi non conosciamo i specifici parametri e metodi di T chiediamo, per calcolare la media, che ci venga passata una funzione a cui sarà delegata l’estrazione dei voti come double dall’oggetto aperto di tipo T, tale metodo è calcolaMedia che accetta come argomento un oggetto di tipo Matematica.