2014-09-05 24 views
5

Ho una funzione di questo tipoUn delegato per una funzione con parametri variabili

void func(params object[] parameters) { 
    //Function Body 
} 

Può accettare parametri della seguente ordinamento

func(10, "hello", 30.0); 
func(10,20); 

e così via.

Volevo creare un delegato Action per la funzione precedente. È possibile? Se no, allora perché?

+0

No, stranamente questo è stato discusso mezz'ora fa! http://stackoverflow.com/a/25689676/1663001 – DavidG

+1

http://stackoverflow.com/questions/4059624/can-i-use-params-in-action-or-func-delegates –

risposta

8

Non è possibile utilizzare le esistenti Action delegati con params, ma è possibile dichiarare il proprio delegato in questo modo:

public delegate void ParamsAction(params object[] arguments) 

Poi:

// Note that this doesn't have to have params, but it can do 
public void Foo(object[] args) 
{ 
    // Whatever 
} 

... 

ParamsAction action = Foo; 
action("a", 10, 20, "b"); 

Naturalmente si possibile creare unAction<object[]> per il metodo esistente, ma si perde l'aspetto params, in quanto non dichiarato in Action<T>. Così, per esempio:

public static void Foo(params object[] x) 
{ 
} 

... 

Action<object[]> func = Foo; 
func("a", 10, 20, "b"); // Invalid 
func(new object[] { "a", 10, 20, "b" }); // Valid 

Quindi, se siete chiamando il delegato dal codice che vuole utilizzare params, è necessario un tipo delegato che comprende che nella dichiarazione (come per la prima parte). Se si desidera creare un delegato che accetta un numero object[], è possibile creare un'istanzaAction<object[]>utilizzando un metodo che ha params nella sua firma - è solo un modificatore, in modo efficace.

-1

Qui è dove si incontrano i limiti della programmazione funzionale in C#: non si può avere un delegato con un numero variabile di parametri generici (i delegati Action hanno un numero fisso di parametri generici). Ma si può trovare utile creare sovraccarichi generici per ogni numero di parametri:

void func<T1>(T1 parameter1) { ... } 
void func<T1,T2>(T1 parameter1, T2 parameter2) { ... } 
void func<T1,T2,T3>(T1 parameter1, T2 parameter2, T3 parameter3) { ... } 

Ciò si ottiene è la capacità di passare quelle funzioni come parametri (ad esempio, per passare loro semplicemente senza utilizzare le espressioni lambda). Quindi, se si dispone di una funzione come questa:

void anotherFunc(Action<string, int> parameter) { ... } 

Poi si può chiamare in questo modo:

anotherFunc(func); 
+0

'non puoi avere un delegare con un numero variabile di parametri. Certo che puoi. – Servy

+0

@Servizio giusto, è possibile, ma non è possibile utilizzare uno dei delegati 'Azione'. – McGarnagle

+0

È vero, ma non è quello che hai detto nella tua risposta. Hai detto che non puoi avere un delegato con un numero variabile di parametri, non che non puoi avere un 'Action' con un numero variabile di parametri. – Servy