32 Stimmen

Übergabe einer Funktion (mit Parametern) als Parameter?

Ich möchte eine generische erstellen, an die ich eine Funktion als Parameter übergeben kann, jedoch kann diese Funktion selbst Parameter enthalten, so...

int foo = GetCachedValue("LastFoo", methodToGetFoo)

Genau das:

protected int methodToGetFoo(DateTime today)
{ return 2; // example only }

Im Wesentlichen möchte ich eine Methode, die den Cache für einen Wert überprüfen wird, andernfalls wird der Wert auf der Grundlage der übergebenen Methode generieren.

Was denken Sie?

52voto

Marc Gravell Punkte 970173

Es klingt, als wollten Sie eine Func<T> :

T GetCachedValue<T>(string key, Func<T> method) {
     T value;
     if(!cache.TryGetValue(key, out value)) {
         value = method();
         cache[key] = value;
     }
     return value;
}

Der Aufrufer kann dies dann auf viele Arten verpacken; für einfache Funktionen:

int i = GetCachedValue("Foo", GetNextValue);
...
int GetNextValue() {...}

oder, wenn es um Argumente geht, einen Abschluss:

var bar = ...
int i = GetCachedValue("Foo", () => GetNextValue(bar));

16voto

Utilice System.Action und einem Lambda-Ausdruck (anonyme Methode). Zum Beispiel:

public void myMethod(int integer) {     
    // Do something
}

public void passFunction(System.Action methodWithParameters) {
    // Invoke
    methodWithParameters();
}

// ...

// Pass anonymous method using lambda expression
passFunction(() => myMethod(1234));

5voto

mqp Punkte 66863

Sie können Ihren eigenen Delegaten erstellen, aber in C# 3.0 finden Sie es vielleicht bequemer, den eingebauten Func<T> Familie delegieren, um dieses Problem zu lösen. Beispiel:

public int GetCachedValue(string p1, int p2,
                          Func<DateTime, int> getCachedValue)
{
    // do some stuff in here
    // you can call getCachedValue like any normal function from within here
}

Diese Methode nimmt drei Argumente entgegen: eine Zeichenkette, ein int und eine Funktion, die einen DateTime-Wert annimmt und einen int zurückgibt. Zum Beispiel:

int foo = GetCachedValue("blah", 5, methodToGetFoo);   // using your method
int bar = GetCachedValue("fuzz", 1, d => d.TotalDays); // using a lambda

Anders Func<T, U, V...> usw. gibt es im Framework, um Methoden mit unterschiedlichen Mengen an Argumenten unterzubringen.

3voto

Dead account Punkte 18876

Erstellen Sie einen Delegaten für die Methode methodToGetFoo

public delegate object GenerateValue(params p);
public event GenerateValue OnGenerateValue;

Definieren Sie GetCachedValue, um den Delegaten zu verwenden

int GetCachedValue(string key, GenerateValue functionToCall);

In der Implementierung von OnGenerateValue können Sie dann die Parameter überprüfen.

2voto

leppie Punkte 111830

Hier ist etwas Einfaches, mit dem ich begonnen habe, das aber noch weiter ausgebaut werden kann (wie ich es für ein kommerzielles Projekt getan habe).

In meinem Fall diente dies zum Zwischenspeichern von Webdienstaufrufen und wurde etwa so verwendet:

WebService ws = new WebService();
var result = ws.Call( x => x.Foo("bar", 1));  // x is the ws instance

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X