title: WeakReference and caching
body: <p>I have a generic cache used to manage the specified type, however, it's not quite working the way I expected it to.  Here is my implementation:</p>
  
  <pre><code>public class GCManagedCache&lt;T&gt; where T : class
  {
      private readonly Dictionary&lt;string, WeakReference&gt; _cache = new Dictionary&lt;string, WeakReference&gt;();
  
      public T this[string key]
      {
          get
          {
              WeakReference weakRef = null;
              if (!_cache.TryGetValue(key, out weakRef))
              {
                  return null;
              }
  
              if (weakRef != null &amp;&amp; weakRef.IsAlive)
              {
                  return weakRef.Target as T;
              }
  
              _cache.Remove(key);
  
              return null;
          }
          set
          {
              _cache[key] = new WeakReference(value);
          }
      }
  }
  </code></pre>
  
  <p>And here is my test:</p>
  
  <pre><code>    [TestMethod]
      public void TestCaching()
      {
          const string KEY = "test";
  
          GCManagedCache&lt;byte[]&gt; cache = new GCManagedCache&lt;byte[]&gt;();
  
          var o = new byte[1024];
          cache[KEY] = o;
  
          var y = cache[KEY];      // &lt;-- seems to keep it alive even though it's nulled out after the next GC call.
  
          GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true);
  
          o = null;
          y = null;
  
          GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true);
  
          var x = cache[KEY];         // &lt;--- returns a valid value when it should be null
          Assert.IsTrue(x == null);
      }
  </code></pre>
  
  <p>This is the line that is causing the unexpected behavior:</p>
  
  <pre><code>var y = cache[KEY];
  </code></pre>
  
  <p>With that line in the final assignment :</p>
  
  <pre><code>var x = cache[KEY];
  </code></pre>
  
  <p>always results in a valid object being returned.  If I remove the assignment to "y", then it works as expected.</p>