.NET Immutability Tip #3: Protect your properties AND your methods.

A common immutability practice is to simply protect the property setter with an immutability flag.  Take a simple class that has a single integer field for to back our property and a single boolean flag to mark it immutable.

using System;

public class SimplyImmutable {
    private int field1 = 0;
    private bool immutable = false;
   
    public SimplyImmutable() {
    }
   
    public int Field1 {
        get { return field1; }
        set {
            if ( !immutable ) {
                field1 = value;
            }
        }
    }
}

As soon as the immutable flag is set, you can no longer set the field value.  This is nice.  Time to add a few methods.  First we need a MakeImmutable method.  This will set our flag.  Normally, our application will set this before giving any other code access to the class.  Second, we'll add an IncrementField method, but we'll make a mistake, so see if you catch it.

public void MakeImmutable() {
    immutable = true;
}

public void IncrementField() {
    field1++;
}

See the mistake yet?  We accessed field1 directly, and didn't use the immutability flag.  This problem goes away if you use the property instead of the private field or if you use the immutability flag.  In this small example the problem is easy to spot.  However, in a larger class with several properties, many backing fields, and maybe 10 or more methods, you can fail to find issues early in the game.  The gem here is to use the property inside of our methods so that we don't have to write a bunch of extra code in each of them to handle immutability.

public void IncrementField() {
    Field1++;
}

What happens if you are setting the Field1 property multiple times?  You start to incur the wrath of the flag check on each set.  If this happens, then go ahead and move your immutability check into your method and then convert over to using the private field again.  Note if you do this process by first using the property and then only later converting over to use the private field and the immutability flag, you can do it on an as needed basis and ensure that you are protecting yourself.

public void IncrementField() {
    if ( !immutable ) { // Work with field multiple times, if not then just use the property instead }
}

This tip has many natural extensions into other gotchas that I'll cover later.  Think for a bit about making our fields protected so they can be accessed from derived classes, and how that might introduce resource access issues.  I'll be examining this abstraction in the next tip.

Published Monday, May 03, 2004 4:15 PM by Justin Rogers

Comments

Tuesday, May 04, 2004 5:08 AM by Dave L

# re: .NET Immutability Tip #3: Protect your properties AND your methods.

It's an interesting pattern. Q: Why wouldn't you want it to signal callers that the object is immutable when calls are made to change its state?

I suppose you can have different categories of immutable objects, ones where the caller does not care if an operation fails and others where an inability to change its state is a "don't care", but it's difficult for me to come up with use cases where the calling code really doesn't care about the success/failure of the operation. Where would you use this?

For the pattern where the caller does care the immutable object could signal the results by throwing an exception, which is non-performant, but there aren't any good alternatives when setting property values. If performance is an issue then the caller should check the immutable flag prior to the call, but that adds overhead too.

I prefer to avoid directly accessing field1 and the flag just to avoid the perf hit of invoking the property setter before the access. Unless you are in a tight loop invoking it thousands of times per second the overhead is unlikely to be a big perf hit, and the downside is that you now have lots of places that have to be touched if changes are made to the property access. This has the feel of a false saving.


Tuesday, May 04, 2004 6:31 AM by Justin Rogers

# re: .NET Immutability Tip #3: Protect your properties AND your methods.

Immutability patterns come in two forms. The first is that you have a single code piece capable of updating some data, and a bunch of others that have access to it. Think about a gaming scenario where I want to share the game state between all of the AI and other code.

That code can't change the state or it would
break the game, and it shouldn't. Nor should it try to change the state.

The second pattern is that a type is mutable for some time where many code points have access to changing it, and then it becomes mutable. In this case once the object becomes immutable your algorithms should stop trying to change the value. Maybe in your case though the fact that they do try to change the value is an exceptional case and something you need to find through debugging. Rather than toss exceptions you might find that you'd rather use asserts instead.

As for knowing an object is immutable, you can always extend a read-only property that returns the immutable flag. Then code can always find out whether or not the object is mutable and you no longer need to rely on the exception.

In general, I think most programmers are to used to owning all of their code. In most cases you are going to share a lot of code, and the mutability is for protection against many sources changing data when they shouldn't. Having an exception in this case could ruin a real-time simulation. After all, once the state is complete, the user shouldn't be changing it anyway.

I'll be covering some extended scenarios soon. MS tends to adopt the private derived encapsulating class (aka ArrayList.ReadOnlyArrayList which derives from ArrayList, but is private and can only be instantiated by calling methods on ArrayList).

Leave a Comment

(required) 
(required) 
(optional)
(required)