<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          淺談MemoryCache的原生插值方式

          共 3058字,需瀏覽 7分鐘

           ·

          2022-01-03 15:45

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

          標(biāo)準(zhǔn)的MemoryCache暴露了如下幾個(gè)屬性和方法:

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

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

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

          var?s?=?new?MemoryCache(new?MemoryCacheOptions?{?});
          var?entry?=?s.CreateEntry("WeChatID");
          entry.Value?=?"精益碼農(nóng)";

          var?f?=??s.TryGetValue("WeChatID",out??object?obj);

          Console.WriteLine(f);
          Console.WriteLine(obj);

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

          是不是很意外。


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

          var?s?=?new?MemoryCache(new?MemoryCacheOptions?{?});
          s.Set("WeChatID",?"精益碼農(nóng)");
          var?f?=?s.TryGetValue("WeChatID",?out?object?obj);

          Console.WriteLine(f);
          Console.WriteLine(obj);

          如此便能正確輸出。

          擴(kuò)展類源碼看一看

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

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

          繼續(xù)追溯CacheEntry實(shí)現(xiàn)的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?!=?null?&&?CanPropagateOptions())
          ????????????????????{
          ????????????????????????PropagateOptions(_previous);
          ????????????????????}
          ????????????????}

          ????????????????_previous?=?null;?//?we?don't?want?to?root?unnecessary?objects
          ????????????}
          ????????}

          注意其中的_cache.SetEntry(this),表示在MemoryCache底層的ConcurrentDictionary集合插入緩存項(xiàng),

          綜上:緩存項(xiàng)CacheEntry需要被Dispose,才能被插入MemoeyCache

          這是怎樣的設(shè)計(jì)模式?IDisposable接口不是用來釋放資源嗎?
          為啥要使用Dispose方法來向MemoryCache插值?
          不能使用一個(gè)明確的Commit方法嗎?

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


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

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

          盡量不要使用C#8.0推出的不帶大括號(hào)的using語法

          ?using?var?entry?=?s.CreateEntry("WeChatID");
          ?entry.Value?=?"精益碼農(nóng)";
          ????????????
          ?var?f?=?s.TryGetValue("WeChatID",?out?object?obj);
          ?...

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

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

          HTTP1.1 Keep-Alive到底算不算長(zhǎng)連接?

          寶藏好物gRPCurl

          SignalR 開發(fā)到生產(chǎn)部署閉坑指南

          SignalR在React/Go技術(shù)棧的實(shí)踐

          我是狀態(tài)機(jī), 一顆永遠(yuǎn)騷動(dòng)的機(jī)器引擎

          大揭秘| 我司項(xiàng)目組Gitlab Flow && DevOps流程

          你怕是對(duì)MD5算法有誤解


          點(diǎn)個(gè)在看你最好看


          瀏覽 29
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  毛片儿小视频 | 91一级A片 | 国产一级a毛一级a做免费的视频 | 操死我网站| 国产玖玖 |