66

I am confused with this code below,

Developer devCopy = (Developer)dev.Clone();

Clone method of Developer class just creating a Employee clone, then how developer get another clone of developer.

public abstract class Employee
{
    public abstract Employee Clone();

    public string Name { get; set; }
    public string Role { get; set; }
}


public class Typist : Employee
{
    public int WordsPerMinute { get; set; }

    public override Employee Clone()
    {
        return (Employee)MemberwiseClone();
    }

    public override string ToString()
    {
        return string.Format("{0} - {1} - {2}wpm", Name, Role, WordsPerMinute);
    }
}


public class Developer : Employee
{
    public string PreferredLanguage { get; set; }

    public override Employee Clone()
    {
        return (Employee)MemberwiseClone();
    }

    public override string ToString()
    {
        return string.Format("{0} - {1} - {2}", Name, Role, PreferredLanguage);
    }
}


Developer dev = new Developer();
dev.Name = "Bob";
dev.Role = "Team Leader";
dev.PreferredLanguage = "C#";

Developer devCopy = (Developer)dev.Clone();
devCopy.Name = "Sue";

Console.WriteLine(dev);
Console.WriteLine(devCopy);

/* OUTPUT

Bob - Team Leader - C#
Sue - Team Leader - C#

*/

Typist typist = new Typist();
typist.Name = "Kay";
typist.Role = "Typist";
typist.WordsPerMinute = 120;

Typist typistCopy = (Typist)typist.Clone();
typistCopy.Name = "Tim";
typistCopy.WordsPerMinute = 115;

Console.WriteLine(typist);
Console.WriteLine(typistCopy);

/* OUTPUT

Kay - Typist - 120wpm
Tim - Typist - 115wpm

*/
Muhammad Raja
  • 1,970
  • 3
  • 28
  • 46
Syed Tayyab Ali
  • 3,643
  • 7
  • 31
  • 36

3 Answers3

92

Because the method MemberwiseClone() is doing this for you. See the documentation

The MemberwiseClone method creates a shallow copy by creating a new object, and then copying the nonstatic fields of the current object to the new object. If a field is a value type, a bit-by-bit copy of the field is performed. If a field is a reference type, the reference is copied but the referred object is not; therefore, the original object and its clone refer to the same object.

Whenever you see a method you don't unerstand, you can trace who has declared it (in Visual Studio, I guess), and in turn see its documentation. That makes things pretty obvious most of the time.

John Cummings
  • 1,949
  • 3
  • 22
  • 38
Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
  • 1
    It's usually all you need to clone. Primitive fields are isolated copies - definitely cloned. Changing a primitive field of a MemberwiseClone will not be noticed in the source object. Object reference fields are the same. Pointing to another object will not affect the other. However, direct after MemberwiseCloning object references point to the same object. The cloning only occurs on the direct object level, it is not a recursive process. In my experience, it's not common that you need a recursive deep clone, so I don't usually bother creating a Deep Clone function. – Kind Contributor Mar 28 '15 at 06:54
20

The function MemberwiseClone creates a new objects whose fields are bit-for-bit copies of those in the original structure. It is a necessary part of any inheritable class which allows cloning without use of Reflection or serialization, but it is only a small piece of the overall puzzle.

If you wish to allow cloning within an inheritable class, you should define a protected virtual T BaseClone<T>() cloning method; the base-level class which descends from Object should call base.MemberwiseClone; all other classes should use base.BaseClone<T> to get the new instance and then replace any mutable cloneable fields with clones of the ones in the original object.

I would also recommend defining the following interfaces:

interface ISelf<out T> {T Self();}
interface ICloneable<out T> : ISelf<T> {T Clone();}

That will allow for situations in which a class may have some descendants which can be cloned and some which cannot. Those which can be cloned can expose public cloning methods (which should chain to BaseClone<theirOwnType>). Methods which need cloneable derivatives of the base type can use parameters of type ICloneable<theBaseType>; this will allow them to accept any cloneable derivative of the base type, even if not all such derivatives share a common base class.

Kevin Panko
  • 8,356
  • 19
  • 50
  • 61
supercat
  • 77,689
  • 9
  • 166
  • 211
11

There are two types of copy: ShallowCopy and DeepCopy.

ShallowCopy copies all value type members and nonstatic fields, and this are exactly what MemberwiseClone() does.

But what about reference type values? This is where DeepCopy is used. By using DeepCopy, references are not copied, but a new object will be generated from the reference.

Note that by using ShallowCopy, the reference addresses are copied, so the copied reference addresses point to the same object. Due to this, changing one object changes all copies.

Consider the following example:

class Person
{
    public int Age { get; set; }
    public string Name { get; set; }
    public DateTime BirthDate { get; set; }
    public IdInfo IdInfo { get; set; }

    public Person ShallowCopy()
    {
        return this.MemberwiseClone() as Person;
    }

    public Person DeepCopy()
    {
        var clone = this.MemberwiseClone() as Person;
        clone.Name = String.Copy(Name);
        clone.IdInfo = new IdInfo(IdInfo.IdNumber);

        return clone;
    }
}

class IdInfo
{
    public int IdNumber { get; set; }
    public IdInfo(int idNumber)
    {
        this.IdNumber = idNumber;
    }
}
Saineshwar Bageri - MVP
  • 3,851
  • 7
  • 41
  • 47
Masoud Darvishian
  • 3,754
  • 4
  • 33
  • 41
  • 2
    Whats the use of calling `clone.Name = String.Copy(Name);` in the `DeepCopy()` method? ASAIK a string is immutable, so even though its a reference type, there should be no rist sharing the same reference in the cloned Person object because chaning Name on one of the Person instances wouldn't affect the other instance, right? – KarloX Nov 17 '22 at 05:16