c#ConcurrentDictionary包装AddOrUpdate并且懒惰不编译

时间:2017-02-13 13:56:21

标签: c# .net lazy-evaluation concurrentdictionary

我想创建一个新类,它将包装当前的.net ConcurrentDictionary,以确保只调用一次GetOrAdd \ AddOrUpdate的Add委托。我在网上看到了几个解决方案,主要的是用懒惰包装TValue,这样可以添加许多懒物,但只有一个可以存活并调用它的价值工厂。

这是我想出的:

public class LazyConcurrentDictionary<TKey, TValue>
{
    private readonly ConcurrentDictionary<TKey, Lazy<TValue>> concurrentDictionary;

    public LazyConcurrentDictionary()
    {
        this.concurrentDictionary = new ConcurrentDictionary<TKey, Lazy<TValue>>();
    }

    public TValue GetOrAdd(TKey key, Func<TKey, TValue> valueFactory)
    {
        var lazyResult = this.concurrentDictionary.GetOrAdd(key, k => new Lazy<TValue>(() => valueFactory(k), LazyThreadSafetyMode.ExecutionAndPublication));

        return lazyResult.Value;
    }

    public TValue AddOrUpdate(TKey key, Func<TKey, TValue> addFactory, Func<TKey, TValue> updateFactory)
    {

        // this one fails with "Cannot convert lambda expression to type 'System.Lazy' because it is not a delegate type"
        var lazyResult = this.concurrentDictionary.AddOrUpdate(key, (k) => new Lazy<TValue>( () => addFactory(k), LazyThreadSafetyMode.ExecutionAndPublication), updateFactory); 

        return lazyResult.Value;
    }
}

我的问题是AddOrUpdate签名,我得到&#34;无法将lambda表达式转换为&#39; System.Lazy&#39;因为它不是代表类型&#34;

我做错了什么?

1 个答案:

答案 0 :(得分:1)

我认为您错过了对此函数的updateFactory的含义。它是从TKeyTValueTValue的功能,而不是从TKeyTValue的功能,它应该从旧的计算更新值。 所以正确的语法应该是这样的:

public TValue AddOrUpdate(TKey key, Func<TKey, TValue> addFactory, 
                                    Func<TValue, TValue> updateFactory)
{
    var lazyResult = this.concurrentDictionary.AddOrUpdate(key,
    (k) => new Lazy<TValue>(() => addFactory(k), 
                       LazyThreadSafetyMode.ExecutionAndPublication),
    (k,v)=>new Lazy<TValue>(()=>updateFactory(v.Value)))
    );

    return lazyResult.Value;
}

甚至(取决于你如何使用它):

public TValue AddOrUpdate(TKey key, Func<TKey, TValue> addFactory, 
                                    Func<TKey, TValue, TValue> updateFactory)
{
    var lazyResult = this.concurrentDictionary.AddOrUpdate(key,
    (k) => new Lazy<TValue>(() => addFactory(k), LazyThreadSafetyMode.ExecutionAndPublication),
    (k,v)=>new Lazy<TValue>(()=>updateFactory(k, v.Value))
    );

    return lazyResult.Value;
}