C# 实现AsyncCache时,为什么在任务上需要惰性包装器?

C# 实现AsyncCache时,为什么在任务上需要惰性包装器?,c#,.net,task,lazy-evaluation,C#,.net,Task,Lazy Evaluation,我在.Net文档中找到了一个关于如何实现AsyncCache的示例。他们建议如下: public class AsyncCache<TKey, TValue> { private readonly Func<TKey, Task<TValue>> _valueFactory; private readonly ConcurrentDictionary<TKey, Lazy<Task<TValue>>> _ma

我在.Net文档中找到了一个关于如何实现AsyncCache的示例。他们建议如下:

public class AsyncCache<TKey, TValue>
{
    private readonly Func<TKey, Task<TValue>> _valueFactory;
    private readonly ConcurrentDictionary<TKey, Lazy<Task<TValue>>> _map;

    public AsyncCache(Func<TKey, Task<TValue>> valueFactory)
    {
        if (valueFactory == null) throw new ArgumentNullException("loader");
        _valueFactory = valueFactory;
        _map = new ConcurrentDictionary<TKey, Lazy<Task<TValue>>>();
    }

    public Task<TValue> this[TKey key]
    {
        get
        {
            if (key == null) throw new ArgumentNullException("key");
            return _map.GetOrAdd(key, toAdd => 
                new Lazy<Task<TValue>>(() => _valueFactory(toAdd))).Value;
        }
    }
}
公共类异步缓存
{
私有只读Func\u valueFactory;
私有只读ConcurrentDictionary\u映射;
公共异步缓存(Func valueFactory)
{
如果(valueFactory==null)抛出新的ArgumentNullException(“加载器”);
_valueFactory=valueFactory;
_map=新的ConcurrentDictionary();
}
公共任务此[TKey]
{
得到
{
如果(key==null)抛出新的ArgumentNullException(“key”);
return\u map.GetOrAdd(key,toAdd=>
新的惰性(()=>_valueFactory(toAdd))。值;
}
}
}
为什么我们不能只使用地图字典中的任务,而不将它包装在一个懒惰的字典中?对我来说,任务本身的行为就像一个懒惰的人,从那个时候起,它只执行一次,然后我们可以通过result属性或等待属性访问结果


那么,有人能解释一下在这里使用Lazy的目的吗?谢谢

在第一次请求值之前,惰性包装不会调用工厂方法。如果没有惰性包装器,所有任务的代码都会提前调用,这有其缺点。是的,但是当我们将一个任务添加到字典
GetOrAdd
时,它会在同一时间被调用,可以多次执行传递的委托,因此它可以创建多个
Lazy
实例,但是您只访问其中一个
,因此只会创建一个
任务
。因此,
Lazy
可能被用作监护人,每个键只创建一个
任务。@PetSerAl几乎肯定是正确的。话虽如此,如果
Func
可能引发异常,我建议
LazyWithNoExceptionCaching
而不是
Lazy
。@mjwill我的观点是,异步方法通常不引发异常,而是返回失败的任务。至少编译器以这种方式生成了
async
方法。因此,使用定制的
Lazy
类几乎没有什么好处,但有更多的代码需要测试和支持。