首页 » 网站建设 » php原生cache技巧_浅谈MemoryCache的原生插值办法

php原生cache技巧_浅谈MemoryCache的原生插值办法

访客 2024-12-05 0

扫一扫用手机浏览

文章目录 [+]

.NET运行时内置了常用的缓存模块:MemoryCache

标准的MemoryCache暴露了如下几个属性和方法:

php原生cache技巧_浅谈MemoryCache的原生插值办法

public int Count { get; }public void Compact(double percentage);public ICacheEntry CreateEntry(object key);public void Dispose();public void Remove(object key);public bool TryGetValue(object key, out object result);protected virtual void Dispose(bool disposing);

但是你利用常规模式去插值/获取值,可能会涌现意想不到的情形。

php原生cache技巧_浅谈MemoryCache的原生插值办法
(图片来自网络侵删)

就如下这样的常规代码:

var s = new MemoryCache(new MemoryCacheOptions { });var entry = s.CreateEntry(\公众WeChatID\公众);entry.Value = \"大众精益码农\"大众;var f = s.TryGetValue(\"大众WeChatID\"大众,out object obj);Console.WriteLine(f);Console.WriteLine(obj);

会输出如下结果:

是不是很意外。

但是看官们一样平常不会利用MemoryCache的原生方法,而是利用位于同一命名空间的 扩展方法Set

var s = new MemoryCache(new MemoryCacheOptions { });s.Set(\"大众WeChatID\"大众, \公众精益码农\"大众);var f = s.TryGetValue(\"大众WeChatID\"大众, out object obj);Console.WriteLine(f);Console.WriteLine(obj);

如此便能精确输出。

扩展类源码看一看

public static TItem Set<TItem>(this IMemoryCache cache, object key, TItem value) { using ICacheEntry entry = cache.CreateEntry(key); entry.Value = value;return value;}

扩展方法与原生方法的差异在于using关键字 (也解释了CacheEntry继续自IDisposable接口)。

连续追溯CacheEntry实现的Dispose方法:

public void Dispose() {if (!_state.IsDisposed) { _state.IsDisposed = true;if (_cache.TrackLinkedCacheEntries) { CacheEntryHelper.ExitScope(this, _previous); } // Don't commit or propagate options if the CacheEntry Value was never set. // We assume an exception occurred causing the caller to not set the Value successfully, // so don't use this entry.if (_state.IsValueSet) { _cache.SetEntry(this);if (_previous != && CanPropagateOptions()) { PropagateOptions(_previous); } } _previous = ; // we don't want to root unnecessary objects } }

把稳个中的_cache.SetEntry(this),表示在MemoryCache底层的ConcurrentDictionary<object, CacheEntry>凑集插入缓存项,

综上:缓存项CacheEntry须要被Dispose,才能被插入MemoeyCache。

这是若何的设计模式?IDisposable接口不是用来开释资源吗?为啥要利用Dispose方法来向MemoryCache插值?不能利用一个明确的Commit方法吗?

这在Github上也有issue谈论,从2017年开始就有大佬质疑这是一个反人类的设计思路,官方为了不引入Break Change,一贯保持到现在。

基于此现状,我们如果利用MemoryCache的原生插值方法, 须要这样:

var s = new MemoryCache(new MemoryCacheOptions { }); using (var entry = s.CreateEntry(\"大众WeChatID\"大众)) { entry.Value = \"大众精益码农\"大众; } var f = s.TryGetValue(\公众WeChatID\"大众, out object obj); ...

只管即便不要利用C#8.0推出的不带大括号的using语法

using var entry = s.CreateEntry(\"大众WeChatID\公众); entry.Value = \"大众精益码农\公众; var f = s.TryGetValue(\公众WeChatID\"大众, out object obj); ...

这种没明确指定using浸染范围的语法,会在函数末端才实行Dispose方法, 导致实行到TryGetValue时,缓存项实在还没插入!


Last
MemoryCache插值的实现过程很奇葩
只管即便利用带明确大括号范围的using语法,C#8.0推出的不带大括号的using语法糖的浸染时候在函数末端,会带来误导。

相关文章