Question Passer la méthode en paramètre en utilisant C #


J'ai plusieurs méthodes toutes avec la même signature (paramètres et valeurs de retour) mais les noms différents et les internes des méthodes sont différents. Je veux passer le nom de la méthode à exécuter à une autre méthode qui appellera la méthode passée.

public int Method1(string)
{
    ... do something
    return myInt;
}

public int Method2(string)
{
    ... do something different
    return myInt;
}

public bool RunTheMethod([Method Name passed in here] myMethodName)
{
    ... do stuff
    int i = myMethodName("My String");
    ... do more stuff
    return true;
}

public bool Test()
{
    return RunTheMethod(Method1);
}

Ce code ne fonctionne pas mais c'est ce que j'essaie de faire. Ce que je ne comprends pas, c'est comment écrire le code RunTheMethod puisque j'ai besoin de définir le paramètre.


521
2018-01-17 21:01


origine


Réponses:


Vous pouvez utiliser le délégué Func dans .net 3.5 comme paramètre dans votre méthode RunTheMethod. Le délégué Func vous permet de spécifier une méthode qui prend un certain nombre de paramètres d'un type spécifique et renvoie un seul argument d'un type spécifique. Voici un exemple qui devrait fonctionner:

public class Class1
{
    public int Method1(string input)
    {
        //... do something
        return 0;
    }

    public int Method2(string input)
    {
        //... do something different
        return 1;
    }

    public bool RunTheMethod(Func<string, int> myMethodName)
    {
        //... do stuff
        int i = myMethodName("My String");
        //... do more stuff
        return true;
    }

    public bool Test()
    {
        return RunTheMethod(Method1);
    }
}

653
2018-01-17 21:08



Vous devez utiliser un déléguer. Dans ce cas, toutes vos méthodes prennent un string paramètre et renvoyer un int - ceci est représenté le plus simplement par le Func<string, int> déléguer1. Ainsi votre code peut devenir correct avec un changement aussi simple que ceci:

public bool RunTheMethod(Func<string, int> myMethodName)
{
    // ... do stuff
    int i = myMethodName("My String");
    // ... do more stuff
    return true;
}

Certes, les délégués ont beaucoup plus de pouvoir que cela. Par exemple, avec C # vous pouvez créer un délégué à partir d'un expression lambda, de sorte que vous pouvez invoquer votre méthode de cette façon:

RunTheMethod(x => x.Length);

Cela va créer une fonction anonyme comme ceci:

// The <> in the name make it "unspeakable" - you can't refer to this method directly
// in your own code.
private static int <>_HiddenMethod_<>(string x)
{
    return x.Length;
}

puis passez ce délégué à la RunTheMethod méthode.

Vous pouvez utiliser des délégués pour les abonnements aux événements, l'exécution asynchrone, les rappels - toutes sortes de choses. Cela vaut la peine de les lire, surtout si vous voulez utiliser LINQ. j'ai un article lequel est la plupart sur les différences entre les délégués et les événements, mais vous pouvez trouver utile de toute façon.


1 Ceci est basé sur le générique Func<T, TResult> déléguer le type dans le cadre; vous pourriez facilement déclarer votre propre:

public delegate int MyDelegateType(string value)

puis faites le paramètre de type MyDelegateType au lieu.


305
2018-01-17 21:02



Vous pouvez également essayer Action Delegate!

 public static int Method1(string mystring)
 {
      return 1;
 }

 public static int Method2(string mystring)
 {
     return 2;
 }

 public bool RunTheMethod(Action myMethodName)
 {
      myMethodName();
      return true;
 }

Et puis appelez votre méthode en utilisant

RunTheMethod(() => Method1("MyString1"));

Ou

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

Ensuite, appelez simplement la méthode

Console.WriteLine(InvokeMethod(new Func<string,int>(Method1), "MyString1"));

Console.WriteLine(InvokeMethod(new Func<string, int>(Method2), "MyString2"));

85
2017-10-14 10:40



public static T Runner<T>(Func<T> funcToRun)
{
    //Do stuff before running function as normal
    return funcToRun();
}

Usage:

var ReturnValue = Runner(() => GetUser(99));

23
2017-08-14 02:50



Vous devriez utiliser un Func<string, int> délégué, qui représente une fonction prenant un string comme argument et renvoyer un int:

public bool RunTheMethod(Func<string, int> myMethod) {
    // do stuff
    myMethod.Invoke("My String");
    // do stuff
    return true;
}

Alors utilisez-le:

public bool Test() {
    return RunTheMethod(Method1);
}

10
2018-01-17 21:03



Si vous voulez pouvoir changer la méthode appelée lors de l'exécution, je vous recommande d'utiliser un délégué: http://www.codeproject.com/KB/cs/delegates_step1.aspx

Cela vous permettra de créer un objet pour stocker la méthode à appeler et vous pourrez le passer à vos autres méthodes quand vous en aurez besoin.


6
2018-01-17 21:05



Bien que la réponse acceptée soit absolument correcte, j'aimerais fournir une méthode supplémentaire.

Je me suis retrouvé ici après avoir fait ma propre recherche d'une solution à une question similaire. Je construis un framework piloté par plugin, et dans ce cadre je voulais que les gens puissent ajouter des éléments de menu au menu des applications à une liste générique sans exposer un réel Menu objet parce que le cadre peut déployer sur d'autres plates-formes qui n'ont pas Menu Objets d'interface utilisateur Il est assez facile d'ajouter des informations générales sur le menu, mais laisser au développeur du plugin suffisamment de liberté pour créer le rappel lorsque le menu est cliqué s'avère pénible. Jusqu'à ce que je me rende compte que j'essayais de réinventer la roue et que les menus normaux appellent et déclenchent le rappel des événements!

Donc, la solution, aussi simple que cela puisse paraître une fois que vous vous en rendez compte, m'a échappé jusqu'à présent.

Créez simplement des classes distinctes pour chacune de vos méthodes actuelles, héritées d'une base si vous en avez besoin, et ajoutez simplement un gestionnaire d'événement à chacune.


1
2018-03-29 13:48



Voici un exemple qui peut vous aider à mieux comprendre comment passer une fonction en paramètre.

Supposons que vous avez Parent page et vous souhaitez ouvrir une fenêtre contextuelle enfant. Dans la page parent, il y a une zone de texte qui doit être remplie en se basant sur la zone de texte popup enfant.

Ici, vous devez créer un délégué.

Parent.cs        // déclaration des délégués        délégué public void FillName (String FirstName);

Maintenant, créez une fonction qui remplira votre zone de texte et la fonction devrait cartographier les délégués

//parameters
public void Getname(String ThisName)
{
     txtname.Text=ThisName;
}

Maintenant, cliquez sur le bouton pour ouvrir une fenêtre contextuelle Child.

  private void button1_Click(object sender, RoutedEventArgs e)
  {
        ChildPopUp p = new ChildPopUp (Getname) //pass function name in its constructor

         p.Show();

    }

Dans le constructeur ChildPopUp, vous devez créer le paramètre 'type de délégué' de la page parent //

ChildPopUp.cs

    public  Parent.FillName obj;
    public PopUp(Parent.FillName objTMP)//parameter as deligate type
    {
        obj = objTMP;
        InitializeComponent();
    }



   private void OKButton_Click(object sender, RoutedEventArgs e)
    {


        obj(txtFirstName.Text); 
        // Getname() function will call automatically here
        this.DialogResult = true;
    }

1
2017-09-24 11:50



Pour partager une solution aussi complète que possible, je vais finir par présenter trois façons différentes de faire, mais maintenant je vais partir du principe le plus fondamental.


Courte introduction

Tous CLR (Exécution du langage commun) les langages (tels que C # et Visual Basic) fonctionnent sous une VM appelée CLI (Interprète de langage commun) qui exécute le code à un niveau supérieur à celui des langages natifs comme C et C ++ (qui compilent directement en code machine). Il s'ensuit que les méthodes ne sont pas des blocs compilés, mais ce ne sont que des éléments structurés que les CLR reconnaissent et utilisent pour sortir leur corps et le réajuster aux instructions en ligne du code machine. Ainsi, vous ne pouvez pas penser à passer une méthode en paramètre, car une méthode ne produit aucune valeur par elle-même: ce n'est pas une expression valide! Donc, vous allez trébucher le concept de délégué.


Qu'est-ce qu'un délégué?

Un délégué représente un pointeur sur une méthode. A cause de (comme je l'ai dit plus haut) une méthode n'est pas une valeur, il y a une classe spéciale dans les langages CLR: Delegate. Cette classe enveloppe n'importe quelle méthode et vous pouvez implicitement convertir n'importe quelle méthode en celle-là.

Regardez l'exemple d'utilisation suivant:

static void MyMethod()
{
    Console.WriteLine("I was called by the Delegate special class!");
}

static void CallAnyMethod(Delegate yourMethod)
{
    yourMethod.DynamicInvoke(new object[] { /*Array of arguments to pass*/ });
}

static void Main()
{
    CallAnyMethod(MyMethod);
}

Les trois manières:

  • Chemin 1
    Utilisez le Delegate classe spéciale directement comme l'exemple ci-dessus. Le problème de cette solution est que votre code ne sera pas coché lorsque vous passerez dynamiquement vos arguments sans les restreindre aux types de ceux dans la déclaration de la méthode.

  • Chemin 2/3 Outre le Delegate classe spéciale, le concept des délégués se propage aux délégués des douanes, qui sont des déclarations de méthodes précédées par le delegate mot-clé et ils se comportent comme une méthode normale. Ils sont ainsi contrôlés, et vous arriverez à un "parfait"code.

Regardez l'exemple suivant:

delegate void PrintDelegate(string prompt);

static void PrintSomewhere(PrintDelegate print, string prompt)
{
    print(prompt);
}

static void PrintOnConsole(string prompt)
{
    Console.WriteLine(prompt);
}

static void PrintOnScreen(string prompt)
{
    MessageBox.Show(prompt);
}

static void Main()
{
    PrintSomewhere(PrintOnConsole, "Press a key to get a message");
    Console.Read();
    PrintSomewhere(PrintOnScreen, "Hello world");
}

Une deuxième option de cette façon de ne pas écrire votre propre délégué personnalisé utilise l'un d'eux déclaré dans les bibliothèques système:

  • Action enveloppe un void sans arguments.
  • Action<T1> enveloppe un void avec un argument.
  • Action<T1, T2> enveloppe un voidavec deux arguments.
  • Etc...
  • Func<TR> enveloppe une fonction avec TR type de retour et sans arguments.
  • Func<TR, T1> enveloppe une fonction avec TR type de retour et avec un argument.
  • Func<TR, T1, T2> enveloppe une fonction avec TR type de retour et avec deux arguments.
  • Etc...

(Cette dernière solution est que beaucoup de personnes ont posté.)


1
2018-05-15 14:30



Voici un exemple sans paramètre: http://en.csharp-online.net/CSharp_FAQ:_How_call_a_method_using_a_name_string

avec params: http://www.daniweb.com/forums/thread98148.html#

vous passez essentiellement dans un tableau d'objets avec le nom de la méthode. vous utilisez ensuite les deux avec la méthode Invoke.

params Object [] paramètres


0
2018-01-17 21:04