Passer la méthode comme 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 va invoquer 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.
10 réponses
vous pouvez utiliser le delegate Func dans .net 3.5 comme paramètre dans votre méthode RunTheMethod. Le délégué Func 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);
}
}
Vous devez utiliser un délégué . Dans ce cas, toutes vos méthodes prennent un paramètre string
et renvoient un paramètre int
- ceci est très simplement représenté par le Func<string, int>
délégué 1 . 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;
}
les Délégués ont beaucoup plus de pouvoir que cela, certes. Par exemple, avec C# vous pouvez créer un délégué à partir d'un lambda expression , pour que vous puissiez invoquer votre méthode de cette façon:
RunTheMethod(x => x.Length);
qui va créer une fonction anonyme comme celle-ci:
// 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;
}
et ensuite passer ce délégué à la méthode RunTheMethod
.
vous pouvez utiliser les délégués pour les abonnements à des événements, l'exécution asynchrone, les callbacks - toutes sortes de choses. Cela vaut la peine de les lire, surtout si vous voulez utiliser LINQ. J'ai un article qui est principalement sur les différences entre les délégués et les événements, mais vous pouvez trouver utile de toute façon.
1 c'est juste basé sur le type de délégué générique Func<T, TResult>
dans le framework; vous pouvez facilement déclarer votre propre:
public delegate int MyDelegateType(string value)
et ensuite faire le paramètre être de type MyDelegateType
à la place.
vous pouvez aussi 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 ensuite appelez votre méthode en utilisant
RunTheMethod(() => Method1("MyString1"));
ou
public static object InvokeMethod(Delegate method, params object[] args)
{
return method.DynamicInvoke(args);
}
alors simplement appeler la méthode
Console.WriteLine(InvokeMethod(new Func<string,int>(Method1), "MyString1"));
Console.WriteLine(InvokeMethod(new Func<string, int>(Method2), "MyString2"));
public static T Runner<T>(Func<T> funcToRun)
{
//Do stuff before running function as normal
return funcToRun();
}
Utilisation:
var ReturnValue = Runner(() => GetUser(99));
vous devez utiliser un Func<string, int>
délégué, qui représente une fonction prenant un string
comme argument et retournant un int
:
public bool RunTheMethod(Func<string, int> myMethod) {
// do stuff
myMethod.Invoke("My String");
// do stuff
return true;
}
puis l'utiliser:
public bool Test() {
return RunTheMethod(Method1);
}
si vous voulez la possibilité de changer quelle méthode est appelée à l'exécution, je recommande l'utilisation d'un délégué: http://www.codeproject.com/KB/cs/delegates_step1.aspx
il vous permettra de créer un objet pour stocker la méthode à appeler et vous pouvez passer cela à vos autres méthodes quand il est nécessaire.
bien que la réponse acceptée soit absolument correcte, j'aimerais fournir une méthode supplémentaire.
j'ai atterri ici après avoir fait ma propre recherche d'une solution à une question similaire.
Je suis en train de construire un framework piloté par plugin, et dans le cadre de cela je voulais que les gens puissent ajouter des éléments de menu au menu applications à une liste générique sans exposer un objet Menu
réel parce que le framework peut se déployer sur d'autres plateformes qui n'ont pas Menu
UI objet. Ajouter des informations générales sur le menu est assez facile, mais permettre au développeur de plugin assez de liberté pour créer le callback pour quand le menu est cliqué s'est avéré être une douleur. Jusqu'à ce que je me rende compte que j'essayais de réinventer la roue et l'appel normal des menus et de déclencher le rappel des événements!
donc la solution, aussi simple que cela paraisse une fois que vous vous en rendez compte, m'a échappé jusqu'à maintenant.
il suffit de créer des classes séparées pour chacun de vos méthodes courantes, héritées d'une base si vous le DEVEZ, et ajoutez simplement un gestionnaire d'événements à chacune.
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 commencer par le principe le plus fondamental.
Brève introduction
All CLR ( Common Language Runtime ) langages (comme C# et Visual Basic) travaillent sous une machine virtuelle appelée CLI ( Langage Commun Interprète ) qui se déroule à l' code à un niveau plus élevé que les langues natives comme C et C++ (qui compilent directement le code machine). Il s'ensuit que les méthodes ne sont pas n'importe quel type de bloc compilé, mais ils sont juste des éléments structurés qui CLR reconnaissent et utilisent pour tirer leur corps et le réajuster aux instructions en ligne du code de la machine. Ainsi, vous ne pouvez pas penser à passer une méthode comme paramètre, parce qu'une méthode ne produit pas de valeur par elle-même: ce n'est pas une expression valide! Donc, vous allez tomber sur le délégué concept.
Qu'est-ce qu'un délégué?
Un délégué représente un pointeur sur une méthode. En raison 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 langues CLR: Delegate
. Cette classe encapsule la méthode, et vous pouvez implicitement convertie en une méthode pour cela.
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 façons:
-
Voie 1
Utilisez la classe spécialeDelegate
directement comme exemple ci-dessus. Le problème de cette solution est que votre code ne sera pas vérifié que vous passez dynamiquement vos arguments sans les restreindre aux types de ceux dans la déclaration de méthode. -
Façon 2/3 Outre le
Delegate
spécial classe, le concept de délégué se propage aux délégués de coutume, qui sont des déclarations de méthodes précédées par le mot-clédelegate
et ils se comportent comme une méthode normale. Ils sont ainsi vérifiés, et vous viendrez à 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 par cette façon de ne pas écrire votre propre délégué personnalisé est d'utiliser l'un d'eux déclaré dans bibliothèques système:
-
Action
enveloppevoid
sans arguments. -
Action<T1>
enveloppevoid
avec un argument. -
Action<T1, T2>
enveloppevoid
avec deux arguments. - et ainsi de suite...
-
Func<TR>
enveloppe une fonction avecTR
type de retour et sans arguments. -
Func<TR, T1>
encapsule un fonction avec le type de retourTR
et avec un argument. -
Func<TR, T1, T2>
enveloppe une fonction avecTR
type de retour et avec deux arguments. - et ainsi de suite...
(cette dernière solution est que beaucoup de gens postés.)
Voici un exemple Qui peut vous aider à mieux comprendre comment passer une fonction en paramètre.
supposez que vous avez Parent page et vous voulez ouvrir une fenêtre popup enfant. Dans la page parent il y a une boîte de texte qui doit être remplie en se basant sur la boîte de texte popup enfant.
Ici, vous devez créer un délégué.
Parent.cs // déclaration des délégués représentant public nul FillName (String FirstName);
maintenant créer une fonction qui remplira votre boîte de texte et la fonction devrait cartographier les délégués
//parameters
public void Getname(String ThisName)
{
txtname.Text=ThisName;
}
maintenant sur le bouton cliquez sur vous devez ouvrir une fenêtre popup enfant.
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 parent / / page
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;
}
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 alors les deux avec la méthode Invoke.
params objet[] params