【问题标题】:c# ConcurrentDictionary wrapping AddOrUpdate with lazy doesn't compilec# ConcurrentDictionary 用惰性包装 AddOrUpdate 无法编译
【发布时间】:2017-02-13 13:56:21
【问题描述】:

我想创建一个新类来包装当前的 .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 签名,我收到“无法将 lambda 表达式转换为类型 'System.Lazy',因为它不是委托类型”

我做错了什么?

【问题讨论】:

    标签: c# .net lazy-evaluation concurrentdictionary


    【解决方案1】:

    我想你误解了这个函数的 updateFactory 的含义。它是从TKey,TValueTValue 的函数,而不是从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;
    }
    

    【讨论】:

    • 当然,编译器在添加委托下标出了错误,所以我错过了,谢谢 Maksim!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多