Что делает метод MemberwiseClone ()? - PullRequest
43 голосов
/ 18 февраля 2010

Я запутался с этим кодом ниже,

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

Метод 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

*/

Ответы [ 2 ]

61 голосов
/ 18 февраля 2010

Потому что метод MemberwiseClone() делает это для вас. См. документацию

Метод MemberwiseClone создает поверхностную копию, создавая новый объект, а затем копируя нестатические поля текущего объекта в новый объект. Если поле является типом значения, выполняется побитовая копия поля. Если поле является ссылочным типом, ссылка копируется, а ссылочный объект - нет; следовательно, исходный объект и его клон ссылаются на один и тот же объект.

Всякий раз, когда вы видите метод, который вы не понимаете, вы можете отследить, кто его объявил (я думаю, в Visual Studio), и, в свою очередь, посмотреть его документацию. Это делает вещи довольно очевидными в большинстве случаев.

14 голосов
/ 17 февраля 2012

Функция MemberwiseClone создает новые объекты, поля которых являются побитовыми копиями полей в исходной структуре. Это необходимая часть любого наследуемого класса, который позволяет клонировать без использования Reflection или сериализации, но это лишь небольшая часть общей головоломки.

Если вы хотите разрешить клонирование в наследуемом классе, вы должны определить 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>; это позволит им принимать любые клонируемые производные базового типа, даже если не все такие производные имеют общий базовый класс.

...