Mutability in the .NET Framework

Long on prose and short on code, this post just explores some patterns involving mutable/immutable objects in the .NET Framework (mutability from an external point-of-view, at least). The punch line comes at the end, for all of those interested in how this relates to ADO.NET Data Services.

In the simples case, we have certains types for which all instances are always immutable, like System.String. Often an immutable type is paired with a builder type. The System.Text.StringBuilder and System.String pair is a classic example, but you also have System.UriBuilder and System.Uri. An interesting API design choice for the latter pair is that the builder mimicks the API for System.Uri by having the same properties. You also have types such as System.Version, where there is no builder type - you simply use the appropriate constructor.

In other cases, an instance may be mutable or not depending on its state. For example, the SqlConnection type has a ConnectionString property which can only be set when the connection is closed. The property can go back and forth from being mutable to being read-only as the connection is set up and torn down.

Sometimes the act of "sealing" an instance is very explicit, like in the case above. In other cases, such as System.Windows.PropertyMetadata, becoming immutable is a side-effect of doing something seemingly unrelated, such as applying it to a particular property. In the case of PropertyMetadata, an IsSealed property is available to let callers know what state the instance is in.

The latter example is also interesting because it shows a common pattern of having objects start off in a mutable state, then transition to read-only and never have the option of transitioning back to mutable. A very elaborate version of this pattern is described in Freezable Objects Overview and is used extensively for graphic objects in Windows Presentation Foundation. In this case, an instance may or may not be "frozen" (made read-only) based on various factors, like dependent objects; support an explicit Freeze method call to make it read-only; and is expected to be able to produce mutable copies by invoking a Clone method. There's actually more to the WPF Freezable implementation, but the documentation does a pretty good job at describing it.

What does this have to do with my recent posts? IDataServiceConfiguration happens to implement one of these patterns. In particular, the object that you get is mutable while InitializeService is executing, but once it's finished, it becomes read-only. Usually you wouldn't even care about this detail because you can't access the parameter out of the method anyway, but if you thought about keeping a reference in a static field and then trying to change that on a per-request basis, you'll find that this isn't possible. This is all part of the work done to ensure that the security and metadata settings initialized through the configuration 'stick' to the service across all requests and provide a uniform interface to callers.