2009-03-02 8 views
20

Я хочу создать родовое, к которому я могу передать функцию в качестве параметра, однако эта функция может включать в себя так, параметры ...Передача функции (с параметрами) в качестве параметра?

int foo = GetCachedValue("LastFoo", methodToGetFoo) 

Такой, что:

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

По существу я хочу иметь метод, который будет проверять кеш для значения, иначе будет генерировать значение, основанное на переданном методе.

Мысли?

+0

Я не знаю, как это сделать, но в качестве примечания этот вопрос, похоже, не имеет ничего общего с дженериками, насколько я могу судить. – recursive

+0

Это вроде немного, может быть. Вероятно, «делегаты» должны заменить «дженерики». – mquander

+0

Извините, я создавал общий метод для этого, поэтому я решил, что это связано. Но передача действительно связана с делегатом, поэтому я буду обновлять. Спасибо – klkitchens

ответ

37

Это звучит, как вы хотите 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)); 
+1

Спасибо, я был очень близок, но не мог понять, как получить парм прямо в родовом.Последний вариант, с закрытием был ключ! Работает как шарм. – klkitchens

+2

Действительно старый здесь, но закрывающая часть была именно тем, что я искал –

4

Вы можете создать свой собственный делегат, но в C# 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...> Различные типы и т.д. существуют в рамках, чтобы приспособить методы с различным количеством аргументов.

3

Создание делегата для метода methodToGetFoo

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

Определение GetCachedValue использовать делегат

int GetCachedValue(string key, GenerateValue functionToCall); 

Тогда в реализации OnGenerateValue вы можете проверить текущие параметры.

2

Here что-то простое, что я начал, что можно сделать немного дальше (как и для коммерческого проекта).

В моем случае это было кэшировать вызовов веб-службы, и использовали что-то вроде:

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

Использование System.Action и лямбда-выражения (Anonimous метод). Например,

public void myMethod(int integer){ 

    //Do something 

} 

public void passFunction(System.Action methodWithParameters){ 

    //Invoke 
    methodWithParameters(); 

} 

//... 

//Pass anonimous method using lambda expression 
passFunction(() => myMethod(1234)); 
Смежные вопросы