【发布时间】:2016-08-12 18:46:00
【问题描述】:
只是为了避免重新发明轮子
我想知道是否已经存在标准 C# 实现来缓存来自长期运行、资源密集型方法的结果。
在我看来,Lazy<T> 是合适的,但不幸的是它似乎缺少索引结果的输入参数。
我希望以下内容有助于澄清:这是我的自定义解决方案。
public class Cached<FromT,ToT>
{
private Func<FromT,ToT> _my_func;
private Dictionary<FromT,ToT> funcDict;
public Cached(Func<FromT,ToT> coreFunc, IEqualityComparer<FromT> comparer = null)
{
_my_func = coreFunc;
if (comparer != null) {
funcDict = new Dictionary<FromT,ToT>(comparer);
} else {
funcDict = new Dictionary<FromT,ToT>();
}
}
public ToT Get(FromT fromKey) {
if (!funcDict.ContainsKey(fromKey)) {
funcDict.Add(fromKey, _my_func(fromKey) );
}
return funcDict[fromKey];
}
}
在下面找到我的单元测试代码。
string DBSimulation(int example, bool quick = false) {
if (!quick) Thread.Sleep(15000);
return example.ToString();
}
[Test]
public void Test03Cached() {
var testCache = new Functional.Cached<int,string>(x => DBSimulation(x));
DateTime checkNow = DateTime.Now;
string logResult = "";
for (int i = 0; i < 24; i++) {
Assert.AreEqual(DBSimulation( i % 3, true), testCache.Get( i % 3));
logResult += String.Format("After {0} seconds => {1} returned from {2} \n",
((TimeSpan)(DateTime.Now - checkNow)).TotalSeconds,
testCache.Get( i % 3), i);
}
Console.WriteLine(logResult);
double elapsed = ((TimeSpan)(DateTime.Now - checkNow)).TotalSeconds;
Assert.LessOrEqual(elapsed, 15*3+1,"cache not working, {0} seconds elapsed", elapsed);
}
及其输出
After 15,0035002 seconds => 1 returned from 1
After 30,0050002 seconds => 2 returned from 2
After 45,0065002 seconds => 0 returned from 3
After 45,0065002 seconds => 1 returned from 4
After 45,0065002 seconds => 2 returned from 5
...
After 45,0065002 seconds => 0 returned from 21
After 45,0065002 seconds => 1 returned from 22
After 45,0065002 seconds => 2 returned from 23
编辑
对于通用 FromT,字典需要 IEqualityComparer
【问题讨论】:
标签: c# caching lazy-evaluation