Posso utilizzare un elenco < T > come una raccolta di puntatori a metodi? (C #)
Domanda
Voglio creare un elenco di metodi da eseguire. Ogni metodo ha la stessa firma. Ho pensato di mettere i delegati in una raccolta generica, ma continuo a ricevere questo errore:
'metodo' è una 'variabile' ma è usato come un 'metodo'
In teoria, ecco cosa vorrei fare:
List<object> methodsToExecute;
int Add(int x, int y)
{ return x+y; }
int Subtract(int x, int y)
{ return x-y; }
delegate int BinaryOp(int x, int y);
methodsToExecute.add(new BinaryOp(add));
methodsToExecute.add(new BinaryOp(subtract));
foreach(object method in methodsToExecute)
{
method(1,2);
}
Qualche idea su come realizzare questo? Grazie!
Soluzione
Devi lanciare oggetto
nell'elenco in un BinaryOp
, o, meglio, usare un parametro di tipo più specifico per l'elenco:
delegate int BinaryOp(int x, int y);
List<BinaryOp> methodsToExecute = new List<BinaryOp>();
methodsToExecute.add(Add);
methodsToExecute.add(Subtract);
foreach(BinaryOp method in methodsToExecute)
{
method(1,2);
}
Altri suggerimenti
Utilizzando .NET 3.0 (o 3.5?) si dispone di delegati generici.
Prova questo:
List<Func<int, int, int>> methodsToExecute = new List<Func<int, int, int>>();
methodsToExecute.Add(Subtract);
methodsToExecute.Add[0](1,2); // equivalent to Subtract(1,2)
List<Func<int, int, int>> n = new List<Func<int, int, int>>();
n.Add((x, y) => x + y);
n.Add((x, y) => x - y);
n.ForEach(f => f.Invoke(1, 2));
Mi piace meglio l'implementazione di Khoth ma penso che ciò che sta causando l'errore del compilatore sia che non si esegue il cast del metodo su BinaryOp prima di provare a invocarlo. Nel tuo ciclo foreach è semplicemente un "oggetto". Cambia la tua foreach in modo che assomigli a Khoth e penso che funzionerebbe.
Ogni volta che sono stato tentato di fare qualcosa del genere, ho scoperto che è generalmente meglio riformattare il tuo progetto per utilizzare il modello di comando, soprattutto perché tutti i tuoi metodi hanno gli stessi parametri. In questo modo consente una flessibilità molto maggiore.
Non l'ho provato ma usando un Elenco < Azione < t > > type dovrebbe essere in grado di farlo.
Avere tutti loro implementare un'interfaccia comune, dire IExecuteable, e quindi avere un Elenco < IExecutable >
Inoltre, usando i delegati:
class Example
{
public delegate int AddDelegate(int x, int y);
public List<AddDelegate> methods = new List<AddDelegate>();
int Execute()
{
int sum = 0;
foreach(AddDelegate method in methods)
{
sum+=method.Invoke(1, 2);
}
return sum;
}
}