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;
Console.WriteLine("Book is alive");\
Book book2 = wr.Target as Book;
book2 = null;
Console.WriteLine("Book is dead");
// Lets see what happens after GC
// Should not be alive
Console.WriteLine("Book is alive");
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.