Ich habe mehrere Methoden, alle mit derselben Signatur (Parameter und Rückgabewerte), aber unterschiedliche Namen und Interna der Methoden sind unterschiedlich. Ich möchte den Namen der Methode, die ausgeführt werden soll, an eine andere Methode übergeben, die die übergebene Methode aufruft.
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);
}
Dieser Code funktioniert nicht, aber ich versuche dies zu tun. Was ich nicht verstehe, ist, wie man den RunTheMethod-Code schreibt, da ich den Parameter definieren muss.
Antworten:
Sie können den Func-Delegaten in .net 3.5 als Parameter in Ihrer RunTheMethod-Methode verwenden. Mit dem Func-Delegaten können Sie eine Methode angeben, die eine Reihe von Parametern eines bestimmten Typs verwendet und ein einzelnes Argument eines bestimmten Typs zurückgibt. Hier ist ein Beispiel, das funktionieren sollte:
quelle
Action
stattFunc<string, int>
.Action<int,string>
einer Methode, die 2 Parameter (int und string) verwendet und void zurückgibt .Func<double,string,int>
entspricht einer Methode, die 2 Parameter (double
undstring
) akzeptiert und zurückgibtint
. Der zuletzt angegebene Typ ist der Rückgabetyp. Sie können diesen Delegaten für bis zu 16 Parameter verwenden. Wenn Sie irgendwie mehr brauchen, schreiben Sie Ihren eigenen Delegierten alspublic delegate TResult Func<in T1, in T2, (as many arguments as you want), in Tn, out TResult>(T1 arg1, T2 arg2, ..., Tn argn);
. Bitte korrigieren Sie mich, wenn ich falsch verstanden habe.Sie müssen einen Delegaten verwenden . In diesem Fall nehmen alle Ihre Methoden einen
string
Parameter und geben einen zurückint
- dies wird am einfachsten durch denFunc<string, int>
Delegaten 1 dargestellt . So kann Ihr Code mit einer so einfachen Änderung wie folgt korrekt werden:Zugegeben, die Delegierten haben viel mehr Macht. Mit C # können Sie beispielsweise einen Delegaten aus einem Lambda-Ausdruck erstellen , sodass Sie Ihre Methode folgendermaßen aufrufen können:
Dadurch wird eine anonyme Funktion wie folgt erstellt:
und übergeben Sie diesen Delegaten dann an die
RunTheMethod
Methode.Sie können Delegaten für Ereignisabonnements, asynchrone Ausführung, Rückrufe - alles Mögliche - verwenden. Es lohnt sich, sie zu lesen, insbesondere wenn Sie LINQ verwenden möchten. Ich habe einen Artikel, in dem es hauptsächlich um die Unterschiede zwischen Delegierten und Veranstaltungen geht, aber Sie finden ihn vielleicht trotzdem nützlich.
1 Dies basiert nur auf dem generischen
Func<T, TResult>
Delegatentyp im Framework. Sie könnten leicht Ihre eigenen deklarieren:und lassen Sie den Parameter stattdessen vom Typ sein
MyDelegateType
.quelle
public **delegate** int MyDelegateType(string value)
?Aus dem Beispiel von OP:
Sie können Action Delegate ausprobieren! Und rufen Sie dann Ihre Methode mit auf
Oder
Dann rufen Sie einfach method auf
quelle
InvokeMethod
Lambda-AnrufRunTheMethod
stattdessen seinVerwendungszweck:
quelle
Um eine möglichst vollständige Lösung zu teilen, werde ich am Ende drei verschiedene Vorgehensweisen vorstellen, aber jetzt gehe ich vom grundlegendsten Prinzip aus.
Eine kurze Einführung
Alle Sprachen, die auf CLR ( Common Language Runtime ) ausgeführt werden, wie C #, F # und Visual Basic, arbeiten unter einer VM, die den Code auf einer höheren Ebene ausführt als Muttersprachen wie C und C ++ (die direkt auf dem Computer kompiliert werden) Code). Daraus folgt, dass Methoden keine Art von kompiliertem Block sind, sondern nur strukturierte Elemente, die CLR erkennt. Sie können also nicht daran denken, eine Methode als Parameter zu übergeben, da Methoden selbst keine Werte erzeugen, da sie keine Ausdrücke sind! Es handelt sich vielmehr um Anweisungen, die im generierten CIL-Code definiert sind. Sie werden sich also dem Delegiertenkonzept stellen.
Was ist ein Delegierter?
Ein Delegat repräsentiert einen Zeiger auf eine Methode. Wie ich oben sagte, ist eine Methode kein Wert, daher gibt es eine spezielle Klasse in CLR-Sprachen
Delegate
, die jede Methode zusammenfasst.Schauen Sie sich das folgende Beispiel an:
Drei verschiedene Wege, das gleiche Konzept dahinter:
Weg 1
Verwenden Sie die
Delegate
spezielle Klasse direkt wie im obigen Beispiel. Das Problem dieser Lösung besteht darin, dass Ihr Code deaktiviert wird, wenn Sie Ihre Argumente dynamisch übergeben, ohne sie auf die Typen in der Methodendefinition zu beschränken.Weg 2
Neben der
Delegate
speziellen Klasse erstreckt sich das Delegatenkonzept auf benutzerdefinierte Delegaten, bei denen es sich um Definitionen von Methoden handelt, denen dasdelegate
Schlüsselwort vorangestellt ist , und die sich wie normale Methoden verhalten. Sie werden dabei überprüft, sodass Sie einen einwandfrei sicheren Code erhalten.Hier ist ein Beispiel:
Weg 3
Alternativ können Sie einen Delegaten verwenden, der bereits im .NET-Standard definiert wurde:
Action
schließt einvoid
ohne Argumente ab.Action<T1>
schließt einvoid
mit einem Argument ab.Action<T1, T2>
schließt avoid
mit zwei Argumenten ab.Func<TR>
schließt eine Funktion mit demTR
Rückgabetyp und ohne Argumente ab.Func<T1, TR>
schließt eine Funktion mit demTR
Rückgabetyp und einem Argument ab.Func<T1, T2, TR>
schließt eine Funktion mit demTR
Rückgabetyp und mit zwei Argumenten ab.(Die letztere Lösung ist diejenige, die die meisten Leute gepostet haben.)
quelle
Func<T1,T2,TR>
Sie sollten einen
Func<string, int>
Delegaten verwenden, der eine Funktion darstellt, die einstring
Argument als Argument verwendet und Folgendes zurückgibtint
:Dann benutze es:
quelle
Test
Methode sollte seinreturn RunTheMethod(Method1);
Wenn Sie ändern möchten, welche Methode zur Laufzeit aufgerufen wird, würde ich die Verwendung eines Delegaten empfehlen: http://www.codeproject.com/KB/cs/delegates_step1.aspx
Sie können damit ein Objekt zum Speichern der aufzurufenden Methode erstellen und dieses bei Bedarf an Ihre anderen Methoden übergeben.
quelle
Während die akzeptierte Antwort absolut korrekt ist, möchte ich eine zusätzliche Methode bereitstellen.
Ich bin hier gelandet, nachdem ich selbst nach einer Lösung für eine ähnliche Frage gesucht hatte. Ich erstelle ein Plugin-gesteuertes Framework und wollte als Teil davon, dass Benutzer Menüelemente zum Anwendungsmenü zu einer generischen Liste hinzufügen können, ohne ein tatsächliches
Menu
Objekt verfügbar zu machen, da das Framework möglicherweise auf anderen Plattformen bereitgestellt wird, die dies nicht habenMenu
Benutzer Benutzeroberfläche bereitgestellt wird Objekte. Das Hinzufügen allgemeiner Informationen zum Menü ist einfach genug, aber es erwies sich als schmerzhaft, dem Plugin-Entwickler genügend Freiheit zu geben, um den Rückruf zu erstellen, wenn auf das Menü geklickt wird. Bis mir klar wurde, dass ich versuchte, das Rad neu zu erfinden und normale Menüs aufzurufen und den Rückruf von Ereignissen auszulösen!Die Lösung, so einfach sie auch klingt, wenn Sie sie erst einmal erkannt haben, ist mir bisher entgangen.
Erstellen Sie einfach separate Klassen für jede Ihrer aktuellen Methoden, die bei Bedarf von einer Basis geerbt werden, und fügen Sie jeder Klasse einen Ereignishandler hinzu.
quelle
Hier ist ein Beispiel, das Ihnen helfen kann, besser zu verstehen, wie eine Funktion als Parameter übergeben wird.
Angenommen, Sie haben eine übergeordnete Seite und möchten ein untergeordnetes Popup-Fenster öffnen. Auf der übergeordneten Seite befindet sich ein Textfeld, das basierend auf dem untergeordneten Popup-Textfeld ausgefüllt werden sollte.
Hier müssen Sie einen Delegaten erstellen.
Parent.cs // Deklaration der Delegaten public delegate void FillName (String FirstName);
Erstellen Sie nun eine Funktion, die Ihr Textfeld ausfüllt, und die Funktion sollte Delegaten zuordnen
Wenn Sie auf die Schaltfläche klicken, müssen Sie ein untergeordnetes Popup-Fenster öffnen.
Im ChildPopUp-Konstruktor müssen Sie einen Parameter vom Typ 'Delegate' der übergeordneten // Seite erstellen
ChildPopUp.cs
quelle
Wenn Sie die Methode als Parameter übergeben möchten, verwenden Sie:
quelle
Hier ist ein Beispiel ohne Parameter: http://en.csharp-online.net/CSharp_FAQ:_How_call_a_method_using_a_name_string
mit Parametern: http://www.daniweb.com/forums/thread98148.html#
Grundsätzlich übergeben Sie ein Array von Objekten zusammen mit dem Namen der Methode. Sie verwenden dann beide mit der Invoke-Methode.
params Object [] -Parameter
quelle
Die zweite Klasse ist Client, der die Speicherklasse verwendet. Es verfügt über eine Main-Methode, die eine Instanz von PersonDB erstellt, und ruft die Process-Methode dieses Objekts mit einer Methode auf, die in der Client-Klasse definiert ist.
quelle