自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

淺談 MemoryCache 的原生插值方式

開發(fā) 后端
這在Github上也有issue討論,從2017年開始就有大佬質(zhì)疑這是一個反人類的設(shè)計思路,官方為了不引入Break Change,一直保持到現(xiàn)在。

[[443154]]

.NET運行時內(nèi)置了常用的緩存模塊:MemoryCache

標準的MemoryCache暴露了如下幾個屬性和方法:

  1. public int Count { get; } 
  2. public void Compact(double percentage); 
  3. public ICacheEntry CreateEntry(object key); 
  4. public void Dispose(); 
  5. public void Remove(object key); 
  6. public bool TryGetValue(object keyout object result); 
  7. protected virtual void Dispose(bool disposing); 

但是你使用常規(guī)模式去插值/獲取值,可能會出現(xiàn)意想不到的情況。

就如下這樣的常規(guī)代碼:

  1. var s = new MemoryCache(new MemoryCacheOptions { }); 
  2. var entry = s.CreateEntry("WeChatID"); 
  3. entry.Value = "精益碼農(nóng)"
  4.  
  5. var f =  s.TryGetValue("WeChatID",out  object obj); 
  6.  
  7. Console.WriteLine(f); 
  8. Console.WriteLine(obj); 

會輸出如下結(jié)果:

是不是很意外。

但是看官們一般不會使用MemoryCache的原生方法,而是使用位于同一命名空間的 擴展方法Set。

  1. var s = new MemoryCache(new MemoryCacheOptions { }); 
  2. s.Set("WeChatID""精益碼農(nóng)"); 
  3. var f = s.TryGetValue("WeChatID"out object obj); 
  4.  
  5. Console.WriteLine(f); 
  6. Console.WriteLine(obj); 

如此便能正確輸出。

擴展類源碼看一看

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

擴展方法與原生方法的差異在于using關(guān)鍵字 (也說明了CacheEntry繼承自IDisposable接口)。

繼續(xù)追溯CacheEntry實現(xiàn)的Dispose方法:

  1. public void Dispose() 
  2.  { 
  3.      if (!_state.IsDisposed) 
  4.      { 
  5.          _state.IsDisposed = true
  6.  
  7.          if (_cache.TrackLinkedCacheEntries) 
  8.          { 
  9.              CacheEntryHelper.ExitScope(this, _previous); 
  10.          } 
  11.  
  12.          // Don't commit or propagate options if the CacheEntry Value was never set
  13.          // We assume an exception occurred causing the caller to not set the Value successfully, 
  14.          // so don't use this entry. 
  15.          if (_state.IsValueSet) 
  16.          { 
  17.              _cache.SetEntry(this); 
  18.  
  19.              if (_previous != null && CanPropagateOptions()) 
  20.              { 
  21.                  PropagateOptions(_previous); 
  22.              } 
  23.          } 
  24.  
  25.          _previous = null; // we don't want to root unnecessary objects 
  26.      } 
  27.  } 

注意其中的_cache.SetEntry(this),表示在MemoryCache底層的ConcurrentDictionary

綜上:緩存項CacheEntry需要被Dispose,才能被插入MemoeyCache。

這是怎樣的設(shè)計模式?IDisposable接口不是用來釋放資源嗎?

為啥要使用Dispose方法來向MemoryCache插值?

不能使用一個明確的Commit方法嗎?

這在Github上也有issue討論,從2017年開始就有大佬質(zhì)疑這是一個反人類的設(shè)計思路,官方為了不引入Break Change,一直保持到現(xiàn)在。

基于此現(xiàn)狀,我們?nèi)绻褂肕emoryCache的原生插值方法, 需要這樣:

  1. var s = new MemoryCache(new MemoryCacheOptions { }); 
  2. using (var entry = s.CreateEntry("WeChatID")) 
  3.      entry.Value = "精益碼農(nóng)"
  4. var f = s.TryGetValue("WeChatID"out object obj); 
  5. ... 

盡量不要使用C#8.0推出的不帶大括號的using語法

  1. using var entry = s.CreateEntry("WeChatID"); 
  2. entry.Value = "精益碼農(nóng)"
  3.             
  4. var f = s.TryGetValue("WeChatID"out object obj); 
  5. ... 

這種沒明確指定using作用范圍的語法,會在函數(shù)末尾才執(zhí)行Dispose方法, 導(dǎo)致執(zhí)行到TryGetValue時,緩存項其實還沒插入!!!

Last

 

  • MemoryCache插值的實現(xiàn)過程很奇葩
  • 盡量使用帶明確大括號范圍的using語法,C#8.0推出的不帶大括號的using語法糖的作用時刻在函數(shù)末尾,會帶來誤導(dǎo)。

 

責任編輯:武曉燕 來源: 精益碼農(nóng)
相關(guān)推薦

2023-09-20 16:11:32

云原生分布式系統(tǒng)

2023-10-26 08:47:30

云原生數(shù)據(jù)采集

2022-09-20 08:00:32

VMWARE云原生

2011-06-20 10:36:29

SEO

2021-07-14 09:18:19

Python插值算法

2009-09-28 13:39:01

Hibernate工作

2009-07-14 12:47:07

WebWork工作方式

2012-11-15 13:52:07

系統(tǒng)密碼加密加密系統(tǒng)安全

2021-07-19 10:43:43

云原生軟件開發(fā)架構(gòu)

2009-09-29 16:16:58

Hibernate H

2012-11-30 14:35:17

2020-12-14 15:28:05

云計算架構(gòu)云原生

2022-05-25 16:32:36

云原生Cloud

2014-12-23 09:57:29

配線架

2023-11-13 09:28:20

跨組件組件化

2011-02-28 11:19:12

雙絞線布線

2023-08-07 15:49:59

CSS顏色插值算法

2011-05-10 17:11:46

PR值

2009-07-03 13:24:56

JSP表單

2009-09-11 10:01:57

Linq對象初始值
點贊
收藏

51CTO技術(shù)棧公眾號