Clone objects in C#


[clone]

A clone of an object is a copy of that object. There are two kinds of clones: shallow and deep.

A shallow clone shares all of the same values as the original object, even if some of those values are references to other object. In that case the clone’s references point to the same objects as the original object’s references.

In contrast, if a property of the original object is a reference, then a deep copy’s reference points to a new object that is a copy of the referenced object.

For example, the Person class has properties FirstName, LastName, Address, Email, and Phone. The Address property is a reference to an object of type StreetAddress.

A shallow clone of a Person object would contain copies of the FirstName, LastName, Email, and Phone properties. Its Address property would hold a reference to the same StreetAddress object used by the original Person object so they would share the address object. If you make a change to the clone’s Address.Street value, then the same change would be visible in the original Person object because the two objects share the same Address object.

A deep clone of a Person object would get a new StreetAddress object so changes to it would not affect the original object’s Address value.

If the objects created by the deep clone also have properties that are objects, then a deep clone should also clone them deeply. For example, suppose a MailingList object contains an array if Person objects. Then a deep clone of a MailingList object should include a new array containing deep copies of the Person objects so they each have new StreetAddress objects.

The following code shows how this example’s Person class provides shallow and deep clones.

// Types of clones.
public enum CloneType
{
    Shallow,
    Deep
}

// Make a clone of the person.
public Person Clone(CloneType clone_type)
{
    // Make a new Person that shares any objects
    // (in this example Address) with this Person.
    Person new_person = new Person()
    {
        FirstName = FirstName,
        LastName = LastName,
        Address = Address,
        Email = Email,
        Phone = Phone
    };

    // If this should be a deep clone, make a new Address object.
    if (clone_type == CloneType.Deep)
    {
        new_person.Address = new StreetAddress()
        {
            Street = Address.Street,
            City = Address.City,
            State = Address.State,
            Zip = Address.Zip
        };
    }

    // Return the new Person.
    return new_person;
}

This code first defines the CloneType enumeration so the program can specify a shallow or deep clone.

The Clone method takes a parameter of type CloneType. It starts by making a new Person object and initializing it with the original object’s values. That makes a shallow copy. Then if the method’s parameter indicates that this should be a deep copy, the code sets the new object’s Address property to a new StreetAddress object initialized with the same values as the original object’s Address.

The example program uses the following code to create and display three Person objects.

private Person person1, person2, person3;
private void Form1_Load(object sender, EventArgs e)
{
    // Make a Person.
    person1 = new Person()
    {
        FirstName = "Ann",
        LastName = "Archer",
        Address = new StreetAddress()
        {
            Street = "101 Ash Ave",
            City = "Ann Arbor",
            State = "MI",
            Zip = "12345"
        },
        Email = "Ann@anywhere.com",
        Phone = "703-287-3798"
    };
    
    // Make shallow and deep clones.
    person2 = person1.Clone(Person.CloneType.Shallow);
    person3 = person1.Clone(Person.CloneType.Deep);

    // Display the objects.
    propPerson.SelectedObject = person1;
    propShallowClone.SelectedObject = person2;
    propDeepClone.SelectedObject = person3;
}

The code first creates a Person object normally. It then creates a shallow clone and a deep clone. It finishes by displaying each of the objects in PropertyGrid controls. For more information about PropertyGrid controls and how this example uses them, see the example Use a PropertyGrid to let the user edit objects in C#.

When the user changes a value in a PropertyGrid, the following code executes. Note that the event handler doesn’t execute until the user moves focus off of the field that has changed to another field or another control.

// A property value changed. Refresh all of the PropertyGrids.
private void propGrid_PropertyValueChanged(
    object s, PropertyValueChangedEventArgs e)
{
    propPerson.Refresh();
    propShallowClone.Refresh();
    propDeepClone.Refresh();
}

This code refreshes all three PropertyGrid controls so they display their current values. If you expand the controls’ Address fields and change the Address value of the original Person or of the shallow copy, you will see the same change appear in the other control’s PropertyGrid. If you change the Address in the deep copy, the other two objects will be unaffected.

In the next post I’ll talk a bit more about clones.


Download Example   Follow me on Twitter   RSS feed   Donate




This entry was posted in algorithms, OOP, syntax and tagged , , , , , , , , , , , , . Bookmark the permalink.

Leave a Reply

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