2010-10-05 8 views
4

En C#, nous pouvons créer des délégués via divers moyens (par exemple, l'action <>, Func <>, délégué, lambdas, etc.). Mais quand vous invoquez ces méthodes, vous devez fournir les valeurs des paramètres pour le délégué, vous invoquez:Comment créer un délégué de méthode entièrement paramétré en C#?

delegate int del(int i); 
del myDelegate = x => x * x; 
int j = myDelegate(5); 

Est-il possible en C# pour encapsuler un délégué de méthode avec les valeurs des paramètres? Essentiellement retarder l'invocation d'une méthode entièrement paramétrée? Vous n'avez donc pas besoin de fournir des valeurs de paramètre au moment de l'appel?

Par exemple quelque chose comme ce code invalide:

delegate int del(int i); 
del myDelegate(5) = x => x * x; 
int j = myDelegate; 

Je suis au courant du cas d'utilisation n'est pas immédiatement évidente. Dans le cas que je suis en train de regarder, j'ai une méthode non-déterministe que je voudrais que l'appelant puisse invoquer sans avoir à contenir ou être conscient des paramètres dont la méthode a besoin. Une façon d'y parvenir serait de créer une classe qui encapsule à la fois les valeurs des paramètres et le délégué de la méthode et de faire en sorte que celle-ci soit référencée et invoquée par l'appelant. Mais je suis juste curieux de savoir s'il y a une manière alternative et plus succincte.

Répondre

12

Ceci est appelé currying.

Par exemple:

Action curried =() => myFunc(5); 

Ou,

Func<int, int, int> multiplier = (x, y) => x * y; 
Func<int, int> doubler = x => multiplier(x, 2); 
int eight = doubler(4); 
1

Vous pouvez toujours envelopper un délégué dans un autre. Comme mentionné SLaks, on appelle cela currying:

Func<int, int> square = i => i * i; 
Func<int> squareFive =() => square(5); 

int j = squareFive(); 
1
Func<int, int> myDelegate = x => x * x; 
Func<int> myDelegate5 =() => myDelegate(5); 
int j = myDelegate5(); 
0

Cela peut se faire raisonnablement bien sans lambdas, à l'aide de certaines classes génériques et des fonctions d'aide. J'ai utilisé une telle approche dans certains codes vb.net/vs2005. Si le but est de générer un MethodInvoker qui appelle une fonction avec trois arguments de types T, U et V, alors créez une classe ParamInvoker < T, U, V > qui contient les champs param1, param2, et param3 (comme types T, U, et V), et Action (de type Action < T, U, V >) et a une méthode DoIt (void) qui appelle Action (param1, param2, param3). Les classes génériques et les fonctions auxiliaires sont répétitives, mais la syntaxe est plutôt sympa. Par exemple (syntaxe vb, de la mémoire et la syntaxe C#, deviner):

 
    TheMethodInvoker = MakeParamInvoker(AddressOf MyFunction, 5, "Hello") 
or 
    TheMethodInvoker = MakeParamInvoker(MyFunction, 5, "Hello") 

en supposant MyFunction prend un entier et une chaîne.

Questions connexes