2017-02-13 82 views
1

我想創建一個新的類,將包裝當前.net ConcurrentDictionary,以確保GetOrAdd \ AddOrUpdate的添加委託將被確保只被調用一次。我在網絡上看到了一些解決方案,主要的一點是懶惰地包裝TValue,這樣可以添加許多懶惰物品,但只有一個可以生存並調用它的價值工廠。c#ConcurrentDictionary包裝AddOrUpdate與懶惰不編譯

這裏就是我想出:

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’,因爲它不是一個委託類型」

我在做什麼錯?

回答

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; 
} 

甚至(取決於你如何wnat使用它):

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; 
} 
當然
+0

,編譯器強調附加委託下的錯誤,所以我我錯過了,謝謝Maksim! – Ofir