This project has moved. For the latest updates, please go here.

[Info] Freezable Pattern

Coordinator
May 2, 2014 at 12:31 PM
Edited May 14, 2016 at 7:26 PM

This article has been moved to GitHub!


The Freezable Pattern helps to prevent Race Conditions in asynchronous code. It defines an object that can be changed into an immutable (frozen) state. In the frozen state it is save to pass this object to other threads.

The object’s internal state can be modified until it is marked as frozen. When the object is frozen then it stays in this immutable state as long the object lives. It is not possible to unfreeze the object so that the internal state can be modified again. If a writeable version of a frozen object is needed then a common approach is to create a clone of it.

The following code snippet shows an example implementation for a base class that can be used to create freezable classes. All derived classes have to ensure that they call first the ThrowIfFrozen method before they modify the object’s internal state. This ensures that if some flawed code tries to modify a frozen object then an exception will be thrown.
public abstract class Freezable
{
    private volatile bool isFrozen;

    public bool IsFrozen { get { return isFrozen; } }

    public void Freeze()
    {
        isFrozen = true;
    }

    protected bool SetProperty<T>(ref T field, T value)
    {
        ThrowIfFrozen();
        if (object.Equals(field, value)) { return false; }
        field = value;
        return true;
    }

    protected void ThrowIfFrozen()
    {
        if (isFrozen)
        {
            throw new InvalidOperationException("The object is frozen and must not be modified anymore.");
        }
    }
}
The SetProperty method can be used in the property setter implementation. It calls first the ThrowIfFrozen method and then sets the internal field if the value has changed. The usage of this method is shown in the next code snippet.
public class Person : Freezable
{
    private string name;

    public double Name
    {
        get { return name; }
        set { SetProperty(ref name, value); }
    }
...
Known uses
Microsoft uses this pattern in WPF. Examples of freezable objects include brushes, pens, transformations, geometries, and animations.

Further readings
  1. Wikipedia: Race Condition
  2. WPF Freezable Objects Overview