Metoda Pass jako parametr za pomocą C#
Mam kilka metod, wszystkie z tym samym podpisem (parametry i wartości zwrotne), ale różne nazwy i wewnętrzne metody są różne. Chcę przekazać nazwę metody do uruchomienia do innej metody, która wywoła metodę passed in.
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);
}
Ten kod nie działa, ale to właśnie próbuję zrobić. Nie rozumiem, jak napisać kod RunTheMethod, ponieważ muszę zdefiniować parametr.
10 answers
Możesz użyć delegata Func w. Net 3.5 jako parametru w metodzie RunTheMethod. Delegat Func pozwala określić metodę, która pobiera szereg parametrów określonego typu i Zwraca pojedynczy argument określonego typu. Oto przykład, który powinien zadziałać:
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);
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-17 21:08:10
Musisz użyć delegata. W tym przypadku wszystkie metody pobierają parametr string
i zwracają int
- jest to najprościej reprezentowane przez delegata Func<string, int>
1. Tak więc Twój kod może stać się poprawny z tak prostą zmianą jak ta:
public bool RunTheMethod(Func<string, int> myMethodName)
{
// ... do stuff
int i = myMethodName("My String");
// ... do more stuff
return true;
}
Delegaci mają o wiele większą władzę. Na przykład w C# możesz utworzyć delegata z wyrażenia lambda , więc możesz wywołać swoją metodę w ten sposób:
RunTheMethod(x => x.Length);
To stworzy funkcja anonimowa jak ta:
// 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;
}
, a następnie przekazać ten delegat do metody RunTheMethod
.
Możesz używać delegatów do subskrypcji zdarzeń, asynchronicznej realizacji, wywołań zwrotnych-wszelkiego rodzaju rzeczy. Warto o nich poczytać, szczególnie jeśli chcemy korzystać z LINQ. Mam Artykuł, który jest głównie o różnicach między delegatami i wydarzeniami, ale i tak może się okazać przydatny.
1 jest to po prostu oparte na generic Func<T, TResult>
typ delegata w frameworku; możesz łatwo zadeklarować swój własny:
public delegate int MyDelegateType(string value)
A następnie niech parametr będzie Typu MyDelegateType
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-26 05:31:29
Możesz również spróbować 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;
}
A następnie wywołaj swoją metodę używając
RunTheMethod(() => Method1("MyString1"));
Lub
public static object InvokeMethod(Delegate method, params object[] args)
{
return method.DynamicInvoke(args);
}
Następnie po prostu wywołaj metodę
Console.WriteLine(InvokeMethod(new Func<string,int>(Method1), "MyString1"));
Console.WriteLine(InvokeMethod(new Func<string, int>(Method2), "MyString2"));
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-17 15:29:44
public static T Runner<T>(Func<T> funcToRun)
{
//Do stuff before running function as normal
return funcToRun();
}
Użycie:
var ReturnValue = Runner(() => GetUser(99));
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-14 02:50:18
Powinieneś użyć delegata Func<string, int>
, który reprezentuje funkcję przyjmującą string
jako argument i zwracającą int
:
public bool RunTheMethod(Func<string, int> myMethod) {
// do stuff
myMethod.Invoke("My String");
// do stuff
return true;
}
Następnie użyj go:
public bool Test() {
return RunTheMethod(Method1);
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-23 21:37:09
Jeśli chcesz mieć możliwość zmiany, która metoda jest wywoływana w czasie wykonywania, polecam użycie delegata: http://www.codeproject.com/KB/cs/delegates_step1.aspx
Pozwoli Ci utworzyć obiekt do przechowywania metody do wywołania i możesz przekazać ją innym metodom, gdy jest to potrzebne.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-17 21:05:52
Chociaż przyjęta odpowiedź jest absolutnie poprawna, chciałbym podać dodatkową metodę.
Wylądowałem tutaj po tym, jak sam szukałem rozwiązania podobnego pytania.
Buduję framework oparty na wtyczkach, a w jego ramach chciałem, aby ludzie mogli dodawać elementy menu do menu aplikacji do ogólnej listy bez wystawiania rzeczywistego obiektu Menu
, ponieważ framework może zostać wdrożony na innych platformach, które nie mają Menu
obiektów UI. Dodawanie ogólnych informacji o menu jest wystarczająco łatwe, ale pozwalając twórcy plugin wystarczająco dużo swobody, aby utworzyć callback po kliknięciu menu okazało się być bólem. Dopóki nie dotarło do mnie, że próbowałem ponownie wynaleźć koło i normalne połączenia menu i wywołać oddzwanianie od zdarzeń!
Po prostu utwórz osobne klasy dla każdej z twoich obecnych metod, odziedziczonych po bazie, jeśli musisz, i po prostu dodaj Zdarzenie opiekun dla każdego.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-29 13:48:34
Aby podzielić się jak najbardziej kompletnym rozwiązaniem, skończę z przedstawieniem trzech różnych sposobów działania, ale teraz zacznę od najbardziej podstawowej zasady.
Krótkie wprowadzenie
Wszystkie języki CLR (Common Language Runtime) (takie jak C# i Visual Basic) pracują pod maszyną wirtualną o nazwie CLI (common Language Interpreter), która uruchamia kod na wyższym poziomie niż języki natywne, takie jak C i C++ (które bezpośrednio kompilują się na maszynie kod). Wynika z tego, że metody nie są żadnym rodzajem skompilowanego bloku, ale są po prostu strukturyzowanymi elementami, które CLR rozpoznaje i używa do wyciągania swojego ciała i przerabiania go do wbudowanych instrukcji kodu maszynowego. Nie możesz więc myśleć o przekazaniu metody jako parametru, ponieważ metoda sama w sobie nie generuje żadnej wartości: nie jest poprawnym wyrażeniem! Więc potkniesz się o koncepcję delegata.Co to jest delegat?
Delegat reprezentuje wskaźnik za metodę. Ponieważ (jak powiedziałem powyżej) metoda nie jest wartością, istnieje specjalna klasa w językach CLR: Delegate
. Ta klasa otacza dowolną metodę i można ją w sposób niejawny przypisać dowolnej metodzie.
Spójrz na następujący przykład użycia:
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);
}
Trzy sposoby:
Sposób 1
Użyj klasy specjalnejDelegate
bezpośrednio jako przykład powyżej. Problem tego rozwiązania polega na tym, że Twój kod będzie odznaczony, gdy przekazujesz dynamicznie swój argumenty bez ograniczania ich do typów zawartych w deklaracji metody.Sposób 2/3 Oprócz specjalnej klasy
Delegate
, koncepcja delegatów rozprzestrzenia się na niestandardowe delegaty, które są deklaracjami metod poprzedzonych słowem kluczowymdelegate
i zachowują się jak normalna metoda. Są tak sprawdzone, a Ty znajdziesz kod" perfect ".
Spójrz na następujący przykład:
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");
}
Druga opcja w ten sposób aby nie pisać własnego delegata niestandardowego, należy użyć jednego z nich zadeklarowanego w bibliotekach systemowych:
-
Action
owijavoid
bez argumentów. -
Action<T1>
owijavoid
jednym argumentem. -
Action<T1, T2>
owijavoid
dwoma argumentami. - i tak dalej...
-
Func<TR>
zawija funkcję z typem zwracanymTR
bez argumentów. -
Func<TR, T1>
zawija funkcję z typem zwracanymTR
i z jednym argumentem. -
Func<TR, T1, T2>
otacza funkcję zTR
return type i z dwoma argumentami. - i tak dalej...
(to ostatnie rozwiązanie polega na tym, że wiele osób opublikowało.)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-15 14:35:52
Oto przykład, który pomoże Ci lepiej zrozumieć, jak przekazać funkcję jako parametr.
Załóżmy, że masz stronę rodzica i chcesz otworzyć wyskakujące okno dziecka. Na stronie nadrzędnej znajduje się pole tekstowe, które należy wypełnić w oparciu o pole tekstowe Popup potomne.
Tutaj musisz utworzyć delegata.
Rodzic.cs // deklaracja delegatów delegat publiczny void FillName (String FirstName);Teraz Utwórz funkcję, która wypełni twoje pole tekstowe i funkcja powinny mapować delegatów
//parameters
public void Getname(String ThisName)
{
txtname.Text=ThisName;
}
Teraz po kliknięciu przycisku musisz otworzyć wyskakujące okno dziecka.
private void button1_Click(object sender, RoutedEventArgs e)
{
ChildPopUp p = new ChildPopUp (Getname) //pass function name in its constructor
p.Show();
}
W Konstruktorze ChildPopUp musisz utworzyć parametr 'typ delegata' strony nadrzędnej //
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;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-25 09:58:29
Oto przykład bez parametru: http://en.csharp-online.net/CSharp_FAQ:_How_call_a_method_using_a_name_string
With params: http://www.daniweb.com/forums/thread98148.html#
W zasadzie przekazujesz tablicę obiektów wraz z nazwą metody. następnie używasz obu z metodą Invoke.
Params obiekt [] parametry
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-17 21:04:36