Передача функции (с параметрами) в качестве параметра?

StackOverflow https://stackoverflow.com/questions/604048

  •  03-07-2019
  •  | 
  •  

Вопрос

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

int foo = GetCachedValue("LastFoo", methodToGetFoo)

Такой , что:

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

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

Мысли?

Это было полезно?

Решение

Звучит так, будто ты хочешь 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));

Другие советы

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

    public void myMethod(int integer){

    //Do something

}

public void passFunction(System.Action methodWithParameters){

    //Invoke
    methodWithParameters();

}

//...

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

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

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

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

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

int GetCachedValue(string key, GenerateValue functionToCall);

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

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

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

WebService ws = new WebService();
var result = ws.Call( x => x.Foo("bar", 1));  // x is the ws instance
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top