Передача функции (с параметрами) в качестве параметра? - PullRequest
23 голосов
/ 03 марта 2009

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

int foo = GetCachedValue("LastFoo", methodToGetFoo)

такой, что:

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

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

Мысли

Ответы [ 5 ]

44 голосов
/ 03 марта 2009

Звучит так, как будто вы хотите 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));
9 голосов
/ 28 октября 2014

Использование 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));
4 голосов
/ 03 марта 2009

Вы можете создать свой собственный делегат, но в 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 голосов
/ 03 марта 2009

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

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

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

int GetCachedValue(string key, GenerateValue functionToCall);

Затем в реализации OnGenerateValue вы можете проверить параметры.

2 голосов
/ 03 марта 2009

Здесь - это нечто простое, что я начал, и я могу пойти немного дальше (как я сделал для коммерческого проекта).

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

WebService ws = new WebService();
var result = ws.Call( x => x.Foo("bar", 1));  // x is the ws instance
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...