01
Aug
2006

Implementing a generic WeakReference<T> in C#

A weak reference lets you hold a reference to an object that will not prevent it from being garbage collected. There are a few scenarios where this might be important - such as listening for events, caching, various MVC patterns.

.NET and Java supports weak references with the aptly named WeakReference class. In .NET it exposes a .Target property of type object that weakly points to whatever you like.

Java also sports a generic WeakReference<T> to give you a strongly typed version so it's somewhat puzzling why .NET doesn't.

Here is my attempt at a WeakReference<T> for .NET. It works fine in the scenarios I've used and performance is close to the non-generic version but a quick glance at the SSCLI code for WeakReference reveals that the standard version is a little more complicated and it's possible there is a reason for that - most likely due to finalizer issues.

using System;
using System.Runtime.InteropServices;

public class WeakReference<T> : IDisposable
{
  private GCHandle handle;
  private bool trackResurrection;

  public WeakReference(T target)
    : this(target, false)
  {
  }

  public WeakReference(T target, bool trackResurrection) {
    this.trackResurrection = trackResurrection;
    this.Target = target;
  }

  ~WeakReference() {
    Dispose();
  }

  public void Dispose() {
    handle.Free();
    GC.SuppressFinalize(this);
  }

  public virtual bool IsAlive {
    get { return (handle.Target != null); }
  }

  public virtual bool TrackResurrection {
    get { return this.trackResurrection; }
  }

  public virtual T Target {
    get {
      object o = handle.Target;
      if ((o == null) || (!(o is T)))
        return default(T);
      else
        return (T)o;
    }
    set {
      handle = GCHandle.Alloc(value,
        this.trackResurrection ? GCHandleType.WeakTrackResurrection : GCHandleType.Weak);
    }
  }
}

I've allowed Target to be settable against my better judgement to bring it more in like with WeakReference. It's still not serializable though unlike WeakReference.

[)amien

Share with others
  • Digg
  • description
  • StumbleUpon
  • description
  • Reddit
  • del.icio.us
  • Google
  • Live
  • Technorati

3 responses to “Implementing a generic WeakReference<T> in C#”


  1. Gravatar 1 Marc Brooks Dec 12th, 2006 at 00:12

    Could you have inherited from WeakReference and simply cast Target as appropriate?

  2. Gravatar 2 Damien Guard Dec 15th, 2006 at 05:12

    You can't change the object type of a property in a subclass.

    [)amien

  3. Gravatar 3 Stephen Sabey Dec 15th, 2008 at 12:12

    I had a similar need and I used inheritance like this:

    Public Class WeakReference(Of T)
    Inherits WeakReference
    Public Shadows Property Target() As T
    Get
    Return CType(MyBase.Target, T)
    End Get
    Set(ByVal value As T)
    MyBase.Target = value
    End Set
    End Property
    Public Sub New(ByVal target As T)
    MyBase.New(target)
    End Sub
    Public Sub New(ByVal target As T, ByVal trackResurrection As Boolean)
    MyBase.New(target, trackResurrection)
    End Sub
    Public Sub New(ByVal info As System.Runtime.Serialization.SerializationInfo, _
    ByVal context As System.Runtime.Serialization.StreamingContext)
    MyBase.New(info, context)
    End Sub
    End Class

Leave a reply




Topics

Interesting

More