What is a WeakReference in C#? To fully understand it, we first need to delve into the internals of the platform, specifically GCHandle. Understanding GCHandle is crucial before we explore WeakReference
and WeakReference<T>
GCHandle is a struct that helps us communicate with the .NET runtime (mostly GC) using P/Invoke. It’s been around since .NET Framework 1.1, but these days, it uses the modern LibraryImport instead of the older DllImport.
If you want to see them all at a glance click
It is a partial struct
with 2 properties.
- You can't instantiate it using the
new
keyword. - You can new it up by calling the
Alloc
method, it accepts 2 parameters. - The
Alloc
method needs the object reference and the type of Handle. - It has four types: Weak, WeakTrackResurrection, Normal, or Pinned.
- Some of its methods are internal and not available for use in our applications.
- It uses
System.IntPtr
ornint
. - It employs the
LibraryImport
attribute, a new way of usingDllImport
. - It uses the
extern
keyword. - It involves the use of
pointers
. - It utilizes the
MethodImpl
attribute. - it calls this C++ code
Enough theory, Let's write some code with Weak
Type and check the available properties and methods.
- Create a Customer object.
- Create a GCHandle with a
Weak
type and reference to the customer. - Print the allocation status and check if the target is not null.
- Retrieve and print the IntPtr(address) representation of the GCHandle.
Let's go and check it out in a real-world situation.
- Create an object from Customer.
- Create a Weak GCHandle for the Customer object.
- *Print * the customer object and leave the scope (
CreateCustomerAndPrintIt
method). - Force GC to collect unreferenced objects.
- Check the Target property of GCHandle it should be null if the Customer has been garbage collected.
Tip:
After garbage collection, the Target property of a GCHandle can become null because the object has been collected. However, IsAllocated stays true because it only checks if the handle field (a memory address) is non-zero. The memory address doesn’t reset, even if the target object is gone.
You might be wondering, "So what?" 😁 What did we solve? We'll see soon enough.
To give you a quick hint: caching! It helps us cache references without causing memory leaks or consuming too much memory in critical applications.
Want something more to think about? I'll tell you: ConditionalWeakTable<TKey, TValue>
uses the same infrastructure.
Let's explore other types of GCHandle in the next post. (WeakTrackResurrection, Normal and Pinned)
Top comments (0)