case
We all know NET runtime has built-in common cache module MemoryCache, which exposes the following properties and methods:
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);
When we use the conventional mode to interpolate and obtain values, unexpected problems may occur, such as the following code:
var mc = new MemoryCache(new MemoryCacheOptions { }); var entry = mc.CreateEntry("MiaoShu"); entry.Value = "Uncle meow"; var f = mc.TryGetValue("MiaoShu",out object obj); Console.WriteLine(f); Console.WriteLine(obj);
After running the code, the output results are as follows:

It's not surprising to see the output result, which is different from what you think. It can be seen from the code that the native MemoryCache method is used, but generally we do not use it. Instead, we use the extension method Set in the same namespace. The code is as follows:
var s = new MemoryCache(new MemoryCacheOptions { }); s.Set("MiaoShu", "Uncle meow"); var f = s.TryGetValue("MiaoShu", out object obj); Console.WriteLine(f); Console.WriteLine(obj);
After running the code, the output is as follows:

analysis
Why did this happen in the previous section? Let's take a look at the source code of Set:
public static TItem Set<TItem>(this IMemoryCache cache, object key, TItem value) { using ICacheEntry entry = cache.CreateEntry(key); entry.Value = value; return value; }
The difference between the extension method and the native method lies in the using keyword, which indicates that CacheEntry inherits from IDisposable. Let's continue to look at the Dispose method implemented by CacheEntry:
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 } }
In the above source code_ cache.SetEntry(this) indicates that the cache item is inserted into the ConcurrentDictionary collection at the bottom of MemoryCache, that is, the cache item CacheEntry needs to be disposed before it can be inserted into MemoryCache. WTF? What the hell is this design? Shouldn't the IDisposable interface be used to release resources? Why use the Dispose method to interpolate to MemoryCache? This problem has been questioned since 2017, but the official has maintained the status quo until now in order not to introduce Break Change. Therefore, according to the current situation, if the native interpolation method of MemoryCache is used, the code needs the following:
var s = new MemoryCache(new MemoryCacheOptions { }); using (var entry = s.CreateEntry("MiaoShu")) { entry.Value = "Uncle meow"; } var f = s.TryGetValue("MiaoShu", out object obj);
Note that try not to use the using syntax without braces introduced by C#8.0
using var entry = s.CreateEntry("MiaoShu"); entry.Value = "Uncle meow"; var f = s.TryGetValue("MiaoShu", out object obj);
The using syntax without braces does not specify the scope of using explicitly. The Dispose method will be executed at the end of the function, resulting in that the cache item has not been inserted when TryGetValue is executed.
summary
The implementation process of MemoryCache interpolation is very wonderful. We should try to use the using syntax with clear braces. The using syntax without braces introduced by C#8.0 is always at the end of the function, which will lead to misunderstanding.