I am .NET developer following it from the first PDC. I love to work on CLR related stuff, Interop and WPF related areas. I design software and I love to design reusable and extensible frameworks. I am married to the love of my life and living in Dhaka, Bangladesh. Shafqat has posted 10 posts at DZone. You can read more from them at their website. View Full User Profile

.NET WeakReference: GC knows the Best

06.23.2008
| 11686 views |
  • submit to reddit

When I first read about weak references in .NET more than 5 years ago, my first thought was to use it for Caching. The concept was already present in Java before .NET since Java had garbage collection before. Still today I don't see many developers using this awesome class.

What is a Weak Reference?

We all know that garbage collectors start cleaning memory for objects that do not have any reference. A weak reference is a way to have some pointer to an object that does have any reference (strong reference). When we need to access a weak referenced object we can just check if the object is alive and then access it if the object is alive at all. Since .NET is a garbage collection based runtime environment, like all GC based runtimes it does not immediately clean up the memory allocated for the instantiated objects. 

Why should we use it?

Not having a strong reference to the object but at the same time having a pointer to the object enables this class to be well suited for caching. 

When to use Weak Reference?

Since GC executes when there is memory pressure and cleans objects that are in memory. At the same time if memory and processing is expensive for your application then you can reduce pressure on memory and processing at the same time. Let try an example ... 

Lets assume that we have an object that contains is 500KB of data and when we fetch it it quite expensive to get because of the IO operation required to fetch it from database and we need to validate it with some rule. And at the same time we have to have 1000 of these objects instantiated with different sets of data. 

We can use traditional cache but that would use too much memory or we can fetch the instance each time for database. Both solutions have its own flaw. The first uses too much memory and the second one uses too much processing. This would be the best solution to use weak reference 

There are 2 cases possible when we need to access any instance of the object in question 

1. It may not be garbage collected: So the object is still in memory and we can associate a strong reference to it and use it. This saves performance but uses memory without any extra pressure since GC takes the best decision when to collect. 

2. It may have been collected and does not exist anymore: In this scenario we will fetch the object again. So we would be using processing power. The memory pressure was high and GC decided to collect and our onject went with that so we need to fetch the object again. Here again we are letting GC decide when the memory pressure is enough that we would to a high processing action. 

So the basic belief behind WeakRefernce is that "GC knows best". It will clean up memory when needed and we puny humans should respect its decision on memory management. 

How to use WeakReferences?

All you need to do is create a WeakReference class with the object in question passed into the constructor. Keep a storng refence to the weak reference object. When need later then check if obect is alive by checking 'IsAlive' property and then use it. The code sample below shows the lifetime of an object when using a weak reference ...

// Create the object
Book book = new Book("My first book", "Me");
// Set weak reference
WeakReference wr = new WeakReference(book);
// Remove any reference to the book by making it null
book = null;

if (wr.IsAlive)
{
Console.WriteLine("Book is alive");\
Book book2 = wr.Target as Book;
Console.WriteLine(book2.Title);
book2 = null;
}
else
Console.WriteLine("Book is dead");

// Lets see what happens after GC
GC.Collect();
// Should not be alive
if (wr.IsAlive)
Console.WriteLine("Book is alive");
else
Console.WriteLine("Book is dead");

The output should be

Book is alive
My first book
Book is dead

So folks ... that's all about weak references.

References
Published at DZone with permission of its author, Shafqat Ahmed. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Dave Amphlett replied on Wed, 2008/10/22 - 10:52am

In the example, what happens if book is garbage collected in between the calls to wr.IsAlive and book2 = wr.Target as Book ? Target returns null if the object has been garbage collected, so the example would NPE when book2 is dereferenced. Checking book2 is not null to prevent this makes the previous call to IsAlive pointless.

I mention this only because I think IsAlive is dangerous exactly because people use it in the way you have in the example. The only safe way to test the reference seems to be to get it with .Target and then test if it's null.

Seems to me that IsAlive is useless at best and dangerous at worst, but I'm interested in any thoughts around this and always open to be persuaded otherwise :)

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.