[英]What is the method MemberwiseClone() doing?
我對下面的這段代碼感到困惑,
Developer devCopy = (Developer)dev.Clone();
Developer 類的 Clone 方法只是創建了一個 Employee 克隆,然后 developer 如何獲得另一個 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
*/
因為MemberwiseClone()
方法正在為您執行此操作。 查看文檔
MemberwiseClone 方法通過創建一個新對象,然后將當前對象的非靜態字段復制到新對象來創建淺拷貝。 如果字段是值類型,則執行該字段的逐位復制。 如果字段是引用類型,則復制引用但不復制引用的對象; 因此,原始對象和它的克隆引用同一個對象。
每當你看到一個你不理解的方法時,你可以追蹤誰聲明了它(我猜是在 Visual Studio 中),然后查看它的文檔。 大多數時候,這讓事情變得非常明顯。
函數MemberwiseClone
創建一個新對象,其字段是原始結構中字段的逐位副本。 它是任何允許在不使用反射或序列化的情況下進行克隆的可繼承類的必要部分,但它只是整個難題的一小部分。
如果您希望允許在可繼承類中進行克隆,您應該定義一個protected virtual T BaseClone<T>()
克隆方法; base.MemberwiseClone
自Object
的基礎類應該調用base.MemberwiseClone
; 所有其他類都應該使用base.BaseClone<T>
來獲取新實例,然后用原始對象中字段的克隆替換任何可變的可克隆字段。
我還建議定義以下接口:
interface ISelf<out T> {T Self();}
interface ICloneable<out T> : ISelf<T> {T Clone();}
這將允許一個類可能有一些可以克隆的后代和一些不能克隆的情況。 那些可以克隆的可以公開公共克隆方法(應該鏈接到BaseClone<theirOwnType>
)。 需要基類型的可ICloneable<theBaseType>
派生類的方法可以使用ICloneable<theBaseType>
類型的參數; 這將允許它們接受基類型的任何可克隆派生類,即使並非所有此類派生類都共享一個公共基類。
有兩種類型的副本: ShallowCopy
和DeepCopy
。
ShallowCopy
將所有valuetype
承包商,客人和nonstatic
字段,這是excactly什么MemberwiseClone()
一樣。
但是referencetype
值呢? 這是使用DeepCopy
地方。 通過使用DeepCopy
,引用不會被復制,但會從引用生成一個新對象。
請注意,通過使用ShallowCopy
,引用地址被復制,因此復制的引用地址指向同一個對象。 因此,更改一個對象會更改所有副本。
考慮以下示例:
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;
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.