C# 如何用C编写一个类似于a(key,B(key,C(key,ValFactory(key)))的递归函数?

C# 如何用C编写一个类似于a(key,B(key,C(key,ValFactory(key)))的递归函数?,c#,function,recursion,functional-programming,C#,Function,Recursion,Functional Programming,如何编写具有以下形式的函数: A(key, B(key, C(key, ValFactory(key)))) 如果A、B和C有此签名: TResult GetOrAdd(string key, Func<string, TResult> generator); TResult Get(string key); 顺便说一句,“链接”函数的数量没有限制,因此它可以是A、B、或A、B、C或A、B、C、D、E等 我将函数A、B、C等存储在LinkedList中 我该怎么称呼他们呢 编辑

如何编写具有以下形式的函数:

A(key, B(key, C(key, ValFactory(key))))
如果A、B和C有此签名:

TResult GetOrAdd(string key, Func<string, TResult> generator);
TResult Get(string key);
顺便说一句,“链接”函数的数量没有限制,因此它可以是A、B、或A、B、C或A、B、C、D、E等

我将函数A、B、C等存储在LinkedList中

我该怎么称呼他们呢

编辑添加一些信息以进行澄清:

我需要这个来实现多级缓存。有几个不同的缓存都实现了“GetOrAdd”函数。第一级缓存只是一个ConcurrentDictionary,它已经有了GetOrAdd函数

缓存的工作方式是,如果一级缓存没有特定密钥的条目,它会尝试在二级缓存中查找。二级缓存在未命中时查找三级缓存,等等


任何缓存都不应该知道另一个缓存,如果要将每个函数存储在链表中,它应该只实现签名
TResult GetOrAdd(string,Func function to callonchemiss)

,为什么不遍历列表并用前面的结果调用下一个func呢?

我给它举了一个小例子。它不使用两个不同的委托,而是只使用一个来简化事情。用户有责任确保作为参数传递的最后一个方法不会尝试访问队列。不过,它可能可以重新安排

public delegate TResult GetOrAdd<TResult>(string key, Queue<GetOrAdd<TResult>> generatorChain);

static T ExecuteChain<T>(string key, params GetOrAdd<T>[] generators)
{
    var queue = new Queue<GetOrAdd<T>>(generators.Skip(1));
    return generators.First()(key, queue);
}

static int A(string key, Queue<GetOrAdd<int>> generatorChain)
{
    var newKey = key.ToUpper();
    //You can perform checks on the queue
    //i.e. if it's empty, throw an exception
    var tempResult = generatorChain.Dequeue()(newKey, generatorChain);
    return tempResult*2;
}

static int B(string key, Queue<GetOrAdd<int>> generatorChain)
{
    var newKey = key.Insert(0, "My string is: ");
    var tempResult = generatorChain.Dequeue()(newKey, generatorChain);
    return tempResult + 1;
}

static int ValFactory(string key, Queue<GetOrAdd<int>> generatorChain)
{
    //Instead of defining another delegate, we just don't use the queue
    //You can still run your checks (i.e. throw exception if not empty)
    return key.GetHashCode();
}
public委托TResult GetOrAdd(字符串键,队列生成器链);
静态T ExecuteCain(字符串键,参数GetOrAdd[]生成器)
{
var queue=新队列(generators.Skip(1));
返回生成器.First()(键,队列);
}
静态int A(字符串键、队列生成器链)
{
var newKey=key.ToUpper();
//您可以对队列执行检查
//i、 如果为空,则抛出异常
var tempResult=generatorChain.Dequeue()(newKey,generatorChain);
返回结果*2;
}
静态int B(字符串键、队列生成器链)
{
var newKey=key.Insert(0,“我的字符串是:”);
var tempResult=generatorChain.Dequeue()(newKey,generatorChain);
返回tempResult+1;
}
静态int值工厂(字符串键、队列生成器链)
{
//我们只是不使用队列,而不是定义另一个委托
//您仍然可以运行检查(即,如果不为空则抛出异常)
return key.GetHashCode();
}
您可以通过以下方式调用链:

var result = ExecuteChain<int>("Hello world", A, B, ValFactory);
var result=ExecuteChain(“你好,世界”,A,B,ValFactory);

给出以下定义:

public delegate TResult GetOrAdd<TResult>(string key, Func<string, TResult> generator);
public delegate TResult Get<TResult>(string key);
请注意,这看起来像是一种

更新:您还可以简化
,并让客户端通过适配器功能使用所需的参数排序:

public static GetOrAdd<TResult> Adapt<TResult>(Get<TResult> factory) {
    return (key, next) => factory(key);
}

public static Func<string, TResult> Chain<TResult>(params GetOrAdd<TResult>[] funcs) {
    if (funcs.Count() == 0) return null; // or return key => default(TResult);
    var head = funcs.First();
    var tail = funcs.Skip(1).ToArray();
    return key => head(key, Chain(tail));
}

...

var result = Chain(A, B, C, Adapt(ValFactory))(key);
publicstaticgetoraddadapt(获取工厂){
返回(键,下一个)=>工厂(键);
}
公共静态函数链(参数GetOrAdd[]funcs){
if(funcs.Count()==0)返回null;//或返回key=>default(TResult);
var head=funcs.First();
var tail=funcs.Skip(1.ToArray();
返回键=>头(键、链(尾));
}
...
var结果=链(A、B、C、自适应(ValFactory))(键);

这与我想要的相反-我想要当前节点从列表中的下一个节点获取它的值,所以按相反的顺序在列表中循环?我仍然对这是一个递归问题感到困惑?!这听起来更像是需要一个函数堆栈/队列。我将尝试这种方法,看看明天是否有效,现在是午夜。谢谢你的发帖!:)你肯定应该展示一些代码。否则就是读心术。
var result = Chain(ValFactory, A, B, C)(key);
public static GetOrAdd<TResult> Adapt<TResult>(Get<TResult> factory) {
    return (key, next) => factory(key);
}

public static Func<string, TResult> Chain<TResult>(params GetOrAdd<TResult>[] funcs) {
    if (funcs.Count() == 0) return null; // or return key => default(TResult);
    var head = funcs.First();
    var tail = funcs.Skip(1).ToArray();
    return key => head(key, Chain(tail));
}

...

var result = Chain(A, B, C, Adapt(ValFactory))(key);