我暂时写了这个方法:
public static FuncWeakCacheFor ( Func provider ) where T: class { var cache = new WeakReference(null); return () => { var x = (T)cache.Target; if( x == null ) { x = provider(); cache.Target = x; } return x; }; }
所以有点背景:
我有一些冗长的遗留方法,看起来有点像这样:
var id = GetDatabaseId(); if(a){ var data = GetLoader().Init(id).GetData(); // expensive! // do stuff with data } if(b){ // don't load data } ... lots more variations, some contain GetLoader().Init(id).GetData(); some don't....
我的潜在解决方案是这样做:
var id = GetDatabaseId(); var loadData = WeakCacheFor(() => GetLoader().Init(id).GetData()); if(a){ var data = loadData(); // do stuff with data } if(b){ // don't load data } ... lots more variations, some contain loadData(); some don't....
我对此的想法:
我不需要缓存超出此方法调用的范围,所以如果GC在方法返回后立即收集它就没问题
如果代码采用不需要加载数据的路径,则不会发生命中
如果它确实需要数据,则如果需要再次将其缓存在弱引用中.
如果GC确实在中途收集,那么它将无关紧要,因为它只会重新加载.
我的问题:
这实际上有用吗?- 在WeakCacheFor
方法中我是否遗漏了任何可能导致无意中被强烈引用的内容?
我是不是太聪明了? - 即使不需要,我是否应该发出命中并将数据缓存在正常的局部变量中?
我怀疑我可能太聪明,但即使我,这似乎是否有其他人喜欢在其他情况下有用的解决方案?
更新:修改功能,因为显然你不能信任.IsAlive
更新:我意识到返回的Func
将在方法结束时超出范围,所以我根本不需要弱参数,正常的ref将正常工作.我想是因为"看不见森林为树木"的案例.
我没有看到使用弱引用的任何意义.一旦你加载了数据,几乎没有理由把它丢弃,直到你确定它不再有用.
你正在实现的是延迟加载模式的变体.坚持简单的模式,只需使用常规的项目参考:
public static FuncLazyLoad (Func provider) where T : class { T item = null; return () => { if (item == null) { item = provider(); } return item; }; }
(还有一个小提示:你使用var
关键字的方式太多了.)