title: IMemoryCache.GetOrCreateAsync returns null
body: <p>I have a lot of <code>NullReferenceException</code> exceptions on the line <code>if (foosDictionary.TryGetValue(id, out var foo))</code> and I cannot in any way reproduce the issue.</p>
  <p>Stack trace:</p>
  <pre><code>System.NullReferenceException: Object reference not set to an instance of an object.
     at MyProject.Service.Baz(Guid id) in CustomClass.cs:line 900
     at MyProject.Service.BazFeature(Guid id) in CustomClassCaller.cs:line 288
  </code></pre>
  <p>line 900 is the line in question. It is a direct reference to the dictionary: <code>if (foosDictionary.TryGetValue(id, out var foo))</code>.</p>
  <p>Below is the code that leads to the problem line:</p>
  <pre class="lang-cs prettyprint-override"><code>public Foo Baz(Guid id) 
  {
  
  Func&lt;Task&lt;Dictionary&lt;Guid, Foo&gt;&gt;&gt; createDictionary =
      async () =&gt; (await repository.GetFoos()).ToDictionary(sm =&gt; sm.Id);
  
  var foosDictionary = await _cache.GetOrCreateAsync&lt;Dictionary&lt;Guid, Foo&gt;&gt;(
      &quot;cacheKey&quot;,
      async cacheEntry =&gt;
      {
          cacheEntry.AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(15);
          return await createDictionary();
      });
  
  if (foosDictionary.TryGetValue(id, out var foo))
  {
      return foo;
  }
  
  }
  // also there's the remaining code, but it shouldn't execute and it is lower than line 900. Anyway, here it is.
  
  var newDictionary = await createDictionary();
  
  if (newDictionary.TryGetValue(id, out var newFoo))
  {
      fooDictionary = newDictionary;
  
      return newFoo;
  }
  
  throw new Exception(&quot;Error&quot;);
  </code></pre>
  <p>The Usual Suspects are:</p>
  <ul>
  <li><code>await repository.GetFoos()</code> - it uses <code>Dapper.QueryAsync</code> method to get <code>IEnumerable&lt;Foo&gt;</code> and it can't return null. Anyway, I tried hardcoding null return - and goes the next step</li>
  <li><code>.ToDictionary()</code> - it will throw on <code>null</code>. And it does if I hardcode the null return. Also it has different stacktrace and points to <code>GetOrCreateAsync</code>, not the line of code in question.</li>
  <li><code>GetOrCreateAsync</code> - all the other suspects will throw and give different stack trace so this must be it. This method returns <code>null</code>, but I can't figure out how and why.</li>
  </ul>
  <p>Like, if there is <code>null</code> on the cache key, it should go and create the value. <code>createDictionary</code> can't return null so it's out of the question. So...how does that even happen? Why?</p>
  <p>Memory cache is registered in Startup like this: <code>services.AddMemoryCache()</code>. I don't know whether it's Scoped or Singleton and the Microsoft docs don't address it in a straightforward way.</p>
  <p>The app is ASP.NET Core 3.1, <code>GetOrCreateAsync</code> extension method is from v6.0.0, but the actual implementation (or so it seems) gets passed as v3.1.0.</p>
  <p>How can I resolve the issue? Can <code>GetOrCreateAsync</code> really return null in some cases? If so, how to reproduce them?</p>
  <p>PS. I've thought about thread 1 getting the entry and then thread 2 somehow nullifying it, but that shouldn't work since thread 1 already has the reference to the dictionary. Right?</p>