Передача функции (с параметрами) в качестве параметра?
Я хочу создать общий, к которому я могу передать функцию в качестве параметра, однако эта функция может включать в себя сами параметры, поэтому...
int foo = GetCachedValue("LastFoo", methodToGetFoo)
Таким образом:
protected int methodToGetFoo(DateTime today)
{ return 2; // example only }
По сути, я хочу иметь метод, который будет проверять кеш для значения, иначе будет генерироваться значение, основанное на переданном методе.
Мысли?
Ответы
Ответ 1
Похоже, вы хотите 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;
}
Вызывающий может затем обернуть это разными способами; для простых функций:
int i = GetCachedValue("Foo", GetNextValue);
...
int GetNextValue() {...}
или где используются аргументы, замыкание:
var bar = ...
int i = GetCachedValue("Foo", () => GetNextValue(bar));
Ответ 2
Использование System.Action и лямбда-выражения (анонимный метод). Например
public void myMethod(int integer){
//Do something
}
public void passFunction(System.Action methodWithParameters){
//Invoke
methodWithParameters();
}
//...
//Pass anonimous method using lambda expression
passFunction(() => myMethod(1234));
Ответ 3
Вы можете создать свой собственный делегат, но в С# 3.0 вам может быть удобнее использовать встроенное семейство делегатов Func<T>
для решения этой проблемы. Пример:
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
}
Этот метод будет принимать три аргумента: строка, int и функция, которая принимает DateTime и возвращает int. Например:
int foo = GetCachedValue("blah", 5, methodToGetFoo); // using your method
int bar = GetCachedValue("fuzz", 1, d => d.TotalDays); // using a lambda
Различные типы Func<T, U, V...>
и т.д. существуют в структуре для размещения методов с различным количеством аргументов.
Ответ 4
Создайте делегат для метода methodToGetFoo
public delegate object GenerateValue(params p);
public event GenerateValue OnGenerateValue;
Определить GetCachedValue для использования делегата
int GetCachedValue(string key, GenerateValue functionToCall);
Затем в реализации OnGenerateValue вы можете проверить параметры.
Ответ 5
Здесь что-то простое, что я начал, что можно сделать немного дальше (как это было для коммерческого проекта).
В моем случае это было для кэширования вызовов веб-сервисов и использовалось что-то вроде:
WebService ws = new WebService();
var result = ws.Call( x => x.Foo("bar", 1)); // x is the ws instance