Skip navigation.

How To Properly Group Partial Class Files in Visual Studio 2005All recent postsOpera 90.1 Is Out

Snapshot vs. Live Collections

Don has recently reminded me of a section in Framework Design Guidelines about live collections and snapshot collections. What’s the difference and why should you care?

Section 8.3.2.1 of the book says:

Collections representing a state at some point in time are called snapshot collections. For example, a collection containing rows returned from a database query would be a snapshot. Collections that always represent the current state are called live collections. For example, a collection of ComboBox items is a live collection.

Consider a trivial example: you read and cache a collection of books from the database. Suppose, some presentation code retrieves it from cache and excludes one or more entries (see source code). What happened is the calling code modified the collection by reference, and these changes were propagated to the cache!

Cloning toward a snapshot

To steer clear of this predicament you need to clone the collection before you return it. This way you produce a “disconnected” snapshot, and the client can modify it at its will.

Unfortunately, cloning guidance is quite vague. For example, the ICloneable interface is confusing because you can never tell if an object implementing this interface performs a deep clone or a shallow clone.

A shallow copy creates a new instance of the same type as the original object, and then copies the nonstatic fields of the original object. If the field is a value type, a bit-by-bit copy of the field is performed. If the field is a reference type, the reference is copied but the referred object is not; therefore, the reference in the original object and the reference in the clone point to the same object.

In contrast, a deep copy of an object duplicates everything directly or indirectly referenced by the fields in the object.

Brad Abrams asked a while ago whether ICloneable should become obsolete. I think it should because it’s too confusing. The Framework Design Guidelines book clearly advises to stay away from this interface (section 8.4).

What I do is add a DeepClone() method to my Domain Model entities and collections (see updated sample code).

There’s a very important point here: if your entities contain only primitives (int, string, double, Guid, etc), then straight assignment to corresponding clone members is fine. If there are references to other objects, you need to invoke DeepClone() on those too. Otherwise you’re back to square one modifying “live” objects by reference.

Comments

Comment permalink 1 Kent Boogaart |
My solution to the vague ICloneable interface was to define my own:

public interface IDeepCloneable
{
T Clone();
}

I have always implemented deep clones by using serialization. Of course, this implies all types in the hierarchy must be marked as serializable.

It seems to me that implementing deep cloning against non-serializable types would be a PITA, both initially and to maintain.

Emails and Notifications

Would you like to be notified when somebody responds to this post?  Would you like to have these comments emailed to you?

TrackBacks

Sorry, TrackBacks are not allowed.

Submit your comment

Please enter only text since all HTML tags except hyperlinks will be stripped. Hyperlinks will become live links. Any comments with flaming or offensive language will be deleted. Be courteous to other posters. Thank you.

Your name (required):
Your email (optional):
Your site's URL (optional):
Enter this number
Type in the number above:
Comment (required):