title: Need a strategy for caching information about an object without keeping it alive
body: <p>I have a library which processes objects (which happen to be immutable). Many times, it processes the same objects over and over again, but it has no way of knowing, so it does a bunch of repeated work.</p>
  
  <p>A good analogy might be that I'm rendering an interface. My render function returns a frame, but 99% of work that went into rendering that frame is used and thrown away. Much of that work can be re-used if the next time I'm asked to render a frame containing that control, I recognize that it's the same control (just maybe with a slightly different state).</p>
  
  <hr>
  
  <p>If this were real life, and I were dealing with people, I'd give everyone an "id card" to give back to me next time they visit, so that I could look them up in my database if I ever saw them again. Unfortunately, in most programming languages (including C#), you can't just "enhance" arbitrary objects with custom data to more easily identify them later.</p>
  
  <p>I considered keeping a cache of objects I've seen before:</p>
  
  <pre><code>Dictionary&lt;Object, ReallyExpensiveInformation&gt; cache = new ...;
  </code></pre>
  
  <p>Or, if we're worried about objects that override "Equals" incorrectly:</p>
  
  <pre><code>Dictionary&lt;CachedObject, ReallyExpensiveInformation&gt; cache = new ...;
  // Where CachedObject is defined as:
  private class CachedObject : IEquatable&lt;CachedObject&gt; {
      Object Value { get; set; }
      // Get the native hash code that is based on the object reference
      override int GetHashCode() =&gt; RuntimeHelpers.GetHashCode(Value);
      // Ensure each new reference is processed, even if they would claim to be equivalent
      override bool Equals(CachedObject other) =&gt; ReferenceEquals(Value, other.Value);
  }
  </code></pre>
  
  <p>These approaches both suffer from the same core problem in my mind, which is that they create a <strong>memory leak</strong> by holding on to objects that might otherwise have been finalized.</p>
  
  <p>I said I encounter the same objects over and over, but I encounter many more that I never see again. I have loads of space for storing <code>ReallyExpensiveInformation</code>, because the final result is small, but the <code>Objects</code> might be big, and I don't know what ones the caller is holding on to, and what ones they are abandoning to be garbage collected. The caller may or may not be keeping a bunch of references to these objects, but if they decide they're done with them, I don't want my cache to be the things keeping them from being garbage collected.</p>
  
  <p>I almost wish there was some way to hook the "reference count" of an object and dump it once I'm the last holdout.</p>
  
  <hr>
  
  <p>Anyways, my next thought would be to have my own "GarbageCollection" phase. Enhance my dictionary with last-accessed times, and purge any entries that haven't been re-used in a while. That's a complex problem to solve though. I'm wondering if I've completely neglected to think of some simpler solution.</p>
  
  <p>Hopefully it's clear that I'm not in control of the objects I'm processing, otherwise I'd enhance their object model.</p>