Dirtyable Objects

I’m going to start this post with a warning : I haven’t yet decided if this class or practice is a good idea. But I thought it was an interesting use of implicit casting operators, and a cool variation on the Nullable<T> pattern.

public class Dirtyable<T>
{
    T value;

    public T Value 
    { 
        get { return value; }
    }

    public bool Dirty { get; private set; }

    public void Clean()
    {
        Dirty = false;
    }

    internal void Set(T newValue)
    {
        value = newValue;
        Dirty = true;
    }

    public static implicit operator T(Dirtyable<T> dirtyable)
    {
        return dirtyable.Value;
    }
    public static implicit operator Dirtyable<T>(T dirtyable)
    {
        return new Dirtyable<T> { value = dirtyable };
    }
}

Motivation

I made this class in an attempt to abstract the concept that objects that are replaced or written to can be marked as “dirty”, then processed and cleaned by an external actor, such that the “on-dirty” processing is only done when it is needed. I feel like this works better than actual “on-changed” C# events in some cases because there can be many writes or many changes to this value, but the only value that matters is the last write; events would do the processing job on every intermediate change.

It’s important to note that my class would only work with immutable objects like primitives or structs, because it isn’t possible (read: easy) watch their mutable state. It can only detect if you write and replace the current object.

Usage

// Host declaration
readonly Dirtyable<Matrix> textureMatrix = new Dirtyable<Matrix>();
public Dirtyable<Matrix> TextureMatrix
{
    get { return textureMatrix; }
    set { textureMatrix.Set(value); }
}

// Modification
mesh.TextureMatrix = new Matrix { M11 = 1, M22 = 1, M33 = 1, M31 = something };

// Access
var m22 = mesh.TextureMatrix.Value.M22;
Matrix m = mesh.TextureMatrix;

// On-dirty processing
if (mesh.TextureMatrix.Dirty)
{
    // This is the "slow" operation
    textureMatrixEffectParameter.SetValue(mesh.TextureMatrix);
    mesh.TextureMatrix.Clean();
}

If you need to access the field a lot and the dereferencing gets annoying, you can also make another public getter in the host class that does it for you. I did that in a couple of occasions.

Thoughts? Objections? Confusion?

A note on heap garbage

The implicit conversion from T to Dirtyable<T> seemed like a good idea at first, but when profiling my code for the Xbox I found out that it was one of the important sources of heap garbage in my code.

This can be avoided by making the “Set” method public and using it as follows :

mesh.TextureMatrix.Set(new Matrix { M11 = 1, M22 = 1, M33 = 1, M31 = something });

Not much uglier, and less stress on weaker GCs. :)

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.