What is the method MemberwiseClone() doing?

C#Design PatternsPrototypeClone

C# Problem Overview


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

*/

C# Solutions


Solution 1 - C#

Because the method MemberwiseClone() is doing this for you. See https://docs.microsoft.com/en-us/dotnet/api/system.object.memberwiseclone">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.

Solution 2 - C#

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.

Solution 3 - C#

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;
    }
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSyed Tayyab AliView Question on Stackoverflow
Solution 1 - C#BozhoView Answer on Stackoverflow
Solution 2 - C#supercatView Answer on Stackoverflow
Solution 3 - C#Masoud DarvishianView Answer on Stackoverflow