Funktionszeiger in C#
Ich nehme an, in gewisser Weise eine (oder beide) Delegate
oder MethodInfo
qualifizieren Sie sich für diese Titel. Jedoch, weder die syntaktische Nettigkeit, die ich Suche. Also, kurz gesagt, Ist es eine Möglichkeit, dass ich schreiben kann, die folgenden:
FunctionPointer foo = //whatever, create the function pointer using mechanisms
foo();
Kann ich nicht verwenden, eine solide Delegierten (also die Verwendung der delegate
Schlüsselwort deklarieren Sie einen Delegaten-Typ), weil es keine Möglichkeit zu wissen, bis Laufzeit die genauen parameter Liste. Als Referenz, hier ist, was ich schon immer liebäugelt mit in LINQPad derzeit, wo B
werden (meist) vom Benutzer generierten code, und so wird Main
, und damit für die Feinheit meiner user, ich bin versucht zu entfernen, die .Call
:
void Main()
{
A foo = new B();
foo["SomeFuntion"].Call();
}
//Define other methods and classes here
interface IFunction {
void Call();
void Call(params object[] parameters);
}
class A {
private class Function : IFunction {
private MethodInfo _mi;
private A _this;
public Function(A @this, MethodInfo mi) {
_mi = mi;
_this = @this;
}
public void Call() { Call(null); }
public void Call(params object[] parameters) {
_mi.Invoke(_this, parameters);
}
}
Dictionary<string, MethodInfo> functions = new Dictionary<string, MethodInfo>();
public A() {
List<MethodInfo> ml = new List<MethodInfo>(this.GetType().GetMethods());
foreach (MethodInfo mi in typeof(Object).GetMethods())
{
for (int i = 0; i < ml.Count; i++)
{
if (ml[i].Name == mi.Name)
ml.RemoveAt(i);
}
}
foreach (MethodInfo mi in ml)
{
functions[mi.Name] = mi;
}
}
public IFunction this[string function] {
get {
if (!functions.ContainsKey(function))
throw new ArgumentException();
return new Function(this, functions[function]);
}
}
}
sealed class B : A {
public void SomeFuntion() {
Console.WriteLine("SomeFunction called.");
}
}
InformationsquelleAutor Matthew Scharley | 2009-07-26
Du musst angemeldet sein, um einen Kommentar abzugeben.
Sagen Sie, Sie wollen, halten Sie die Anzahl und Art der Parameter geöffnet, aber Sie können tun, dass mit einem delgate:
Dies ist genau die gleiche Sache, die Sie derzeit haben. Versuchen Sie dies:
Können Sie denken, eine Instanz-Methode delegieren als sehr ähnlich zu Ihrem
Function
- Klasse: ein Objekt einerMethodInfo
. So gibt es keine Notwendigkeit, neu zu schreiben.Auch Funktionszeiger in C und C++ sind nicht näher, was Sie brauchen: Sie können nicht an ein Objekt gebunden Instanz und Funktion, und auch Sie sind statisch typisiert, nicht dynamisch typisiert.
Wenn Sie wollen, "wrap", eine andere Methode in einer DynamicFunc delegieren, versuchen Sie dies:
dann:
Hinweis, dass ich mit einer statischen Methode
Foo
also ich passnull
für das Beispiel, aber wenn es eine Instanz-Methode, ich würde mich übergeben das Objekt zu binden.Program
passiert zu sein, die Klasse die statische Methoden definiert sind.Natürlich, wenn Sie das falsche argument-Typen, dann bekommst du Fehler zur Laufzeit. Ich würde wohl nach einem Weg suchen, um Ihr Programm entwerfen, damit Sie so viel Art von Informationen erfasst wird zur compile-Zeit wie möglich.
Das ist viel komplexer... hängen.
Okay, vielleicht nicht so Komplex... siehe update.
Compile-Zeit für die
B
Klasse runtime, wie ich schon sagte, es ist user-generiert, so dass leider keine Fehler es wird behandelt, indem Ihnen (und es gibt gute Bestimmungen, Fehler-reporting, etc., zu tun).Fair genug - in Anlehnung an Einstein, ein Programm sollte so statisch typisierte wie möglich-aber nicht statisch-typisierte-er.
InformationsquelleAutor Daniel Earwicker
Hier ist ein weiteres Stück code, den Sie nutzen könnten; Reflexion ist eher langsam, also, wenn Sie erwarten, dass Ihre Dynamischen Funktionsaufrufen werden Häufig aufgerufen, Sie nicht wollen-Methode.Aufrufen innerhalb des Delegaten:
Und Sie können es verwenden, wie diese:
Dieser wird etwas schneller sein; jeder dynamische Aufruf beinhaltet 1 typecheck pro param, 2 Anrufe und eine array-Konstruktion aufgrund der params-Stil vorbei.
Aus Neugier habe ich zeitlich diese Technik (mit zwei Parametern) gegen meins, und festgestellt, dass meine Methode hat einen overhead von drei und eine halbe Millionstel Sekunde pro Anruf. Also ich vermute, der Aufwand ist unwahrscheinlich, dass ein Problem in einer echten Anwendung; hängt davon ab, welche Art von Dingen, die Ihre Benutzer werden dabei in Ihren Funktionen.
InformationsquelleAutor Eamon Nerbonne