#829 – Add Comments to Indicate Shallow vs. Deep Copying

When you include a copy constructor or Clone method in your class, you should let users of your code know whether these operations are doing shallow or deep copies.

You can indicate whether the copy operation is shallow or deep using XML Documentation Comments.  These comments will then be exposed to Intellisense and within the Object Browser in Visual Studio.  (Provided that you have access to the source code).

For example:

    public class Dog
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public DogCollar Collar { get; set; }

        // Standard constructor
        public Dog(string name, int age)
        {
            Name = name;
            Age = age;
        }

        /// <summary>
        /// Make a (deep) copy of specified Dog
        /// </summary>
        /// <param name="otherDog">Dog to copy</param>
        public Dog(Dog otherDog)
        {
            Name = otherDog.Name;
            Age = otherDog.Age;
            Collar = new DogCollar(otherDog.Collar);
        }
    }

Intellisense will now show this comment:
829-001
As will the Object Browser:

829-002

Advertisement

#775 – Copying an Array of Anonymously-Typed Objects

You can create an implicitly-typed array that contains an array of anonymously-typed objects.

            var movies = new[] {
                new { Title = "North By Northwest", Year = 1959, Director = "Alfred Hitchcock" },
                new { Title = "Zelig", Year = 1983, Director = "Woody Allen" },
                new { Title = "King Kong", Year = 2005, Director = "Peter Jackson" }};

If you’d like to create a copy of this array, you can use the Clone method.  This will create a new array of the same type and copy all of the anonymously-typed elements to the new array.

            var copy = movies.Clone();

#266 – You Can’t Prevent a Method from Changing the Contents of Reference Types

We saw that even when you pass a variable by value to a method, if that variable is a reference to an object, the method can change the contents of the object.

C# doesn’t have a built-in language construct that allows you to tell the compiler to prohibit a method from changing the contents of an object that a parameter references.  (In C++, we can do this with the const keyword).

In C#, if you want to prevent a method from changing an object, you need to first clone your original object and pass a copy of the object to the method. (You’ll want to make a deep copy of the object).

Here’s an example of using the DeepCopy<T> method to pass a copy of the object.

            kirby.BarkAt(DeepCopy<Dog>(jack));


#143 – An Example of Implementing ICloneable for Deep Copies

Here’s an example of implementing ICloneable in two custom classes so that you can use the Clone method to do a deep copy.

To do a deep copy of the Person class, we need to copy its members that are value types and then create a new instance of Address by calling its Clone method.

        public class Person : ICloneable
        {
            public string LastName { get; set; }
            public string FirstName { get; set; }
            public Address PersonAddress { get; set; }

            public object Clone()
            {
                Person newPerson = (Person)this.MemberwiseClone();
                newPerson.PersonAddress = (Address)this.PersonAddress.Clone();

                return newPerson;
            }
        }

The Address class uses MemberwiseClone to make a copy of itself.

        public class Address : ICloneable
        {
            public int HouseNumber { get; set; }
            public string StreetName { get; set; }

            public object Clone()
            {
                return this.MemberwiseClone();
            }
        }

Cloning a Person:

            Person herClone = (Person)emilyBronte.Clone();

#141 – Implementing ICloneable for a Custom Type

A type can choose to implement the ICloneable interface, which includes the single Clone method.  The intent of the Clone method is to create a copy of the object.

The simplest way to create a copy of the object is to call the Object.MemberwiseClone method.

        public class Person : ICloneable
        {
            public string LastName { get; set; }
            public string FirstName { get; set; }
            public Person(string lastname, string firstname)
            {
                LastName = lastname;
                FirstName = firstname;
            }

            public object Clone()
            {
                return this.MemberwiseClone();
            }
        }

If your intention is to make a deep copy and your type contains only members that are value types, this is sufficient.  However, if the type contains members that are reference types, you’ll have to do more in order to get a deep copy.

#139 – Using the Array.Clone Method to Make a Shallow Copy of an Array

You can use the Clone method to copy all of an array’s elements to a new array.  The arrays’ elements must be of the same type.  Each element of the source array is copied to the destination array.

If the arrays contain a value type, you can change values in the destination array after copying without impacting values in the source array.

But if the arrays contain a reference type, the references to the objects are copied, so the destination array will point to the same objects as the source array.  A change in any object will therefore be seen by both arrays. This is known as a shallow copy.

            Person[] folks1 = new Person[2];
            folks1[0] = new Person("Bronte", "Emily");
            folks1[1] = new Person("Bronte", "Charlotte");

            // Copy the folks1 array
            Person[] folks2 = (Person[])folks1.Clone();

            // Change name of person in folks1
            folks1[1].FirstName = "Elvis";

            // Note that object in folks2 has also changed
            Console.WriteLine(folks2[1].FirstName);     // Elvis