1

I am developing a class library.

One utility method is called frequently and is being passed a complex third party object. The method uses data from the model that is time consuming to gather. Thus, for performance reasons, I would like to cache the data into a Dictionary class so that the necessary data is gathered once and then made available for all consecutive calls.

However, for several reasons it is not convenient to demand that the consumer of the library maintain an object instance where the dictionary could be stored.

Is it possible to create an object that can be accessed like a static field, but which would be collected if another (designated) object is collected?

Quasi code:

SomeMethodRequiringALotOfDataFromHugeSystem(detector detectorInHugeSystem)
{
   //access HugeSystem from a property in the dectector.
   //find if Huge System already has a Dictioary.
   //Build a Dictionary from data in Huge system if necessary.

   //(Not possible?) Associate the dictionary to the HugeSystem object instance so that Dictionary will be collected if HugeSystem instance is collected.

   // Perform time efficient task based on Dictionary.
}
Tormod
  • 4,551
  • 2
  • 28
  • 50
  • Under what circumstances would the detector object be collected? – groverboy Dec 04 '13 at 15:21
  • Bad idea, don't do this. You need a timer that periodically checks if the client object hasn't been collected yet. Which you do with WeakReference.IsAlive. – Hans Passant Dec 04 '13 at 15:27
  • I'm reaching through the detector in order to get at the "huge system". The method need this data in order to service the detector. However, as it is expensive to build, I would like to reuse the cache in consecutive calls when handling various detectors within the same "huge system". – Tormod Dec 04 '13 at 19:57

2 Answers2

1

I think you could get this to work with a ConditionalWeakTable. It is primarily designed for language compilers, but nothing stops you from using it for another purpose.

ConditionalWeakTable automatically removes the key/value entry as soon as no other references to a key exist outside the table

So, if you want to create an object A that will be collected when object B is collected, you would add {key=B, value=A} to the ConditionalWeakTable. You can access A anytime with yourTable.TryGetValue(B). Make sure to not have any other permanent references to A anywhere else, then A should be collected when B is collected.

(keep in mind that the garbage collector will not collect objects immediately after they are no longer referenced. Especially large objects may automatically end up in generation 2, which is only collected occasionally)

see also this stackoverflow answer regarding the usage of ConditionalWeakTable

Community
  • 1
  • 1
HugoRune
  • 13,157
  • 7
  • 69
  • 144
0

WeakReference is made specifically for this kind of case.

A weak reference allows the garbage collector to collect an object while still allowing an application to access the object. If you need the object, you can still obtain a strong reference to it and prevent it from being collected.

Euphoric
  • 12,645
  • 1
  • 30
  • 44
  • That's kind of the reverse. Weak references allows me to reference an object without this preventing it from being collected. My question is: can I create an object A that will be collected when object B is collected without B knowing about A? – Tormod Dec 04 '13 at 14:37
  • @Tormod There is no way to do it the way you imagine it. Only way is to keep WeakReference for dictionary of each HugeObject and hope GC won't touch them too much. – Euphoric Dec 04 '13 at 14:46