55 votes

Comment passer une fonction en tant que paramètre en C# ?

Est-il possible de passer une fonction comme paramètre en C# ? Je peux le faire en utilisant les classes Func ou Action, mais cela m'oblige à déclarer toute la signature de la fonction en une seule fois. Lorsque j'essaie d'utiliser Delegate, j'obtiens une erreur de compilation indiquant qu'il est impossible de convertir un groupe de méthodes en Delegate.

Je travaille sur Axial et j'essaie de permettre aux utilisateurs d'appeler des services web. Ce que je recherche, c'est la possibilité de créer la classe proxy de Visual Studio, puis de passer la fonction générée. La signature de la fonction n'a pas d'importance car le code généré utilise uniquement le nom de la fonction. Cependant, j'aimerais transmettre la fonction au lieu du nom pour deux raisons : la possibilité d'utiliser la propriété Url du proxy et une erreur de compilation si le service web n'existe pas ou est mis à jour dans Visual Studio.

public void AlertIt(object o) {
    Axial.DOM.Window.Alert(o.ToString());
}
public void CallAddService() {
    object[] param = new object[] { int.Parse(txtA.Text), int.Parse(txtB.Text) };
    Axial.ServerScript.CallWebService(new WSProxy.WS().Add, param, AlertIt, AlertIt);
}

class Axial.ServerScript {
    public void CallWebService(Delegate method, object[] param, Action<object> successCallback, Action<object> failureCallback) {
        // translate to javascript (already working)
    }
}

52voto

P Daddy Points 14228

Je pense que ce que vous voulez est :

static object InvokeMethod(Delegate method, params object[] args){
    return method.DynamicInvoke(args);
}

static int Add(int a, int b){
    return a + b;
}

static void Test(){
    Console.WriteLine(InvokeMethod(new Func<int, int, int>(Add), 5, 4));
}

Imprimez "9".

46voto

Jon Skeet Points 692016

La conversion d'un groupe de méthodes, d'une méthode anonyme ou d'une expression lambda en un délégué nécessite que le compilateur connaisse le type exact du délégué. Cependant, vous pourriez potentiellement utiliser des expressions lambda et des variables capturées pour rendre cela plus simple :

public void InvokeMethod(Action action)
{
    action();
}

public int Add(int a, int b)
{
    return a + b;
}

public void Test()
{    
    InvokeMethod(() => Add(2, 3));
}

Cela retarde l'invocation de la manière normale, mais en enveloppant l'appel réel à Add dans une plaine Action délégué.

Si cela ne répond pas à vos besoins, vous pouvez peut-être nous en dire un peu plus sur ce que vous essayez vraiment d'obtenir.

EDIT : Si c'est du code généré, vous pouvez faire un cast vers un Func<...> avec les bons arguments de type - en supposant qu'il n'y en ait pas trop. En dehors de cela, il n'y a pas vraiment de moyen de passer un groupe de méthodes. Il y a eu des appels occasionnels pour un opérateur "infoof(...)" (comme typeof mais pour les membres) qui vous donnerait un MemberInfo, mais cela n'existe pas vraiment.

4voto

Jon Limjap Points 46429

Vous devriez d'abord avoir un délégué

delegate int Operation(int a, int b)

alors ça devient :

public void InvokeMethod(Operation method, object target, object param)
{
    method((int) target, (int) param);
}

Il n'est pas nécessaire de faire un appel à l'invocation.

Comme pour dbone, je ne vois pas pourquoi vous auriez besoin d'un tableau params[]. Pourriez-vous clarifier l'utilisation étendue des paramètres ?

Par ailleurs, je vais devoir corriger quelque chose dans votre question, car cela va provoquer une erreur de compilation :p

3voto

dbones Points 2242

Jetez un coup d'œil à l'utilisation des délégués : voici un excellent exemple.

Exemple de délégué

pourquoi utilisez-vous la réflexion ? y aura-t-il jamais un nombre différent de paramètres ? ou savez-vous que la signature de la méthode restera constante (rappelez-vous aussi que C# supporte le mot-clé params[])

params c#

HTH

Bones

3voto

Jarek Points 2092

Regardez Série sur la programmation fonctionnelle par Justin Etheredge. Vous devriez y trouver la solution à votre problème.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X