What is the method MemberwiseClone() doing?
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
*/
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.
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.
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;
}
}