简体   繁体   中英

Passing a Function (with parameters) as a parameter?

I want to create a generic to which I can pass a function as a parameter, however this function may include parameters itself so...

int foo = GetCachedValue("LastFoo", methodToGetFoo)

Such that:

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

Essentially I want to have a method that will check the cache for a value, otherwise will generate the value based on the passed in method.

Thoughts?

It sounds like you want a 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;
}

The caller can then wrap this in many ways; for simple functions:

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

or where arguments are involved, a closure:

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

Use System.Action and a lambda expression (anonymous method). For example:

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

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

// ...

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

You can create your own delegate, but in C# 3.0 you may find it more convenient to use the built-in Func<T> delegate family to solve this problem. Example:

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
}

This method will take three arguments: a string, an int, and a function that takes a DateTime and returns an int. For example:

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

Different Func<T, U, V...> etc. types exist in the framework to accommodate methods with different amounts of arguments.

Create a delegate for the method methodToGetFoo

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

Define GetCachedValue to use the delegate

int GetCachedValue(string key, GenerateValue functionToCall);

Then in the implementation of OnGenerateValue you can check the param's.

Here is something simple I started that can be taken a bit further (as I did for a commercial project).

In my case this was to cache web service calls, and was used something like:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM