This is the ninth post in my ongoing series covering the abstractions in Sasa. Previous posts:
- Sasa.Parsing - type-safe, extensible lexing and parsing framework
- Sasa.Dynamics - type-safe polytypic/reflective programming
- Sasa.Func - Type-Safe Delegate Combinators
- Sasa.Option - Handling Optional Values
- Sasa.Result - Handling Exceptional Values
- Sasa.Numbers - Generic Number Extensions
- Sasa.Strings - General String Extensions
- Sasa.Types - Runtime Types And CLR Metadata
System.WeakReference is a special runtime class used for collection and finalization of resources that have no other live references. The only problem is that the encapsulated value is of type "object", and so using it requires a lot more casting than it should. More often than not, a WeakReference will only encapsulate a value of one type, so this casting is often superfluous.
Enter Sasa.Weak<T>, which is a struct that wraps WeakReference and provides a typed interface to encapsulated values. As a struct, it does not incur any additional memory allocation costs, and the casting it performs are operations you would likely have to do anyway, so the overhead of the typed interface is virtually nil. Sasa.Weak<T> is available in the core Sasa.dll assembly.
Sasa.Weak<T>.HasValue
Sasa.Weak<T>.HasValue has the same purpose as Weak<T>.IsAlive, but fulfills the requirements to satisfy the IResolvable<T> interface:
string original = new string("hello world!".ToCharArray()); Weak<string> foo = original; Console.WriteLine(foo.HasValue); // lose all live references and run collection original = null; GC.Collect(); GC.WaitForPendingFinalizers(); Console.WriteLine(foo.HasValue); // outputs: // true // false
Sasa.Weak<T>.IsAlive
Sasa.Weak<T>.IsAlive checks whether the target of the weak reference has yet to be collected:
string original = new string("hello world!".ToCharArray()); Weak<string> foo = original; Console.WriteLine(foo.IsAlive); // lose all live references and run collection original = null; GC.Collect(); GC.WaitForPendingFinalizers(); Console.WriteLine(foo.IsAlive); // outputs: // true // false
Sasa.Weak<T>.Value
Sasa.Weak<T>.Value obtains the current value encapsulated in the weak reference, or null if the object has been collected:
string original = new string("hello world!".ToCharArray()); Weak<string> foo = original; Console.WriteLine(foo.Value); // lose all live references and run collection original = null; GC.Collect(); GC.WaitForPendingFinalizers(); Console.WriteLine(foo.Value ?? "<null>"); // outputs: // hello world! // <null>
The Value property also fulfills the requirements for the IValue<T> interface.
Sasa.Weak<T>.TryGetValue
Sasa.Weak<T>.TryGetValue checks whether a weak reference to a target is alive, and returns a live reference to that target in one step:
string original = new string("hello world!".ToCharArray()); Weak<string> foo = original; Console.WriteLine(foo.TryGetValue(out original)); Console.WriteLine(original); // lose all live references and run collection original = null; GC.Collect(); GC.WaitForPendingFinalizers(); Console.WriteLine(foo.TryGetValue(out original)); Console.WriteLine(original ?? "<null>"); // outputs: // true // hello world! // false // <null>
This method also satisfies the requirements for the IVolatile<T> interface.
Comments