MemberwiseClone()在做什么?

问题描述 投票:47回答:2

我对下面的这段代码感到困惑,

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

Developer类的克隆方法只是创建一个Employee克隆,然后开发人员如何获得另一个开发人员克隆。

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# design-patterns prototype clone
2个回答
65
投票

因为方法MemberwiseClone()正在为您执行此操作。参见the documentation

MemberwiseClone方法通过创建新对象,然后将当前对象的非静态字段复制到新对象来创建浅表副本。如果字段是值类型,则将执行该字段的逐位复制。如果字段是引用类型,则引用被复制,但引用的对象不被复制;因此,原始对象及其克隆引用相同的对象。

[只要您看到一个您不理解的方法,就可以跟踪谁声明了它(我想在Visual Studio中),然后查看它的文档。在大多数情况下,这使事情变得很明显。


14
投票

函数MemberwiseClone创建一个新对象,这些对象的字段是原始结构中字段的逐位复制。它是任何可继承类的必要组成部分,该类允许在不使用反射或序列化的情况下进行克隆,但这只是整个难题的一小部分。

如果希望允许在可继承类中进行克隆,则应定义protected virtual T BaseClone<T>()克隆方法;源自Object的基层类应调用base.MemberwiseClone;其他所有类都应使用base.BaseClone<T>获取新实例,然后将任何可变的可复制字段替换为原始对象中那些字段的副本。

我也建议定义以下接口:

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

这将允许一个类可能有一些后代可以克隆而有些则不能克隆的情况。可以克隆的可以公开公共克隆方法(应该链接到BaseClone<theirOwnType>)。需要基本类型的可克隆导数的方法可以使用类型为ICloneable<theBaseType>的参数。这将使它们能够接受任何可克隆的基本类型的派生类,即使并非所有此类派生类都具有相同的基本类。

© www.soinside.com 2019 - 2024. All rights reserved.