2010-02-18 14 views
28

Estoy confundido con este código de abajo,¿Cuál es el método que hace MemberwiseClone()?

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

método Clone de la clase desarrollador acaba de crear un clon del empleado, entonces, ¿cómo conseguir desarrollador otro clon del desarrollador.

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 

*/ 

Respuesta

45

Debido a que el método de MemberwiseClone() está haciendo esto para usted. Ver the documentation

El método MemberwiseClone crea una copia superficial mediante la creación de un nuevo objeto y, a continuación, copiar los campos no estáticos del objeto actual al nuevo objeto. Si un campo es un tipo de valor, se realiza una copia bit por bit del campo. Si un campo es un tipo de referencia, la referencia se copia pero el objeto referido no; por lo tanto, el objeto original y su clon se refieren al mismo objeto.

Cuando veas un método que no entiendes, puedes rastrear quién lo ha declarado (en Visual Studio, supongo) y, a su vez, ver su documentación. Eso hace las cosas bastante obvias la mayor parte del tiempo.

+0

Por lo general, todo lo que necesita para clonar. Los campos primitivos son copias aisladas, definitivamente clonadas. No se notará el cambio de un campo primitivo de MemberwiseClone en el objeto fuente. Los campos de referencia del objeto son iguales. Apuntar a otro objeto no afectará al otro. Sin embargo, directamente después de las referencias al objeto MemberwiseCloning apuntan al mismo objeto. La clonación solo ocurre en el nivel de objeto directo, no es un proceso recursivo. En mi experiencia, no es común que necesites un clon profundo recursivo, por lo que normalmente no me molesto en crear una función Deep Clone. – Todd

11

La función MemberwiseClone crea un nuevo objeto cuyos campos son copias bit a bit de aquellos en la estructura original. Es una parte necesaria de cualquier clase heredable que permite la clonación sin el uso de Reflection o serialización, pero es solo una pequeña parte del rompecabezas general.

Si desea permitir la clonación dentro de una clase heredable, debe definir un método de clonación protected virtual T BaseClone<T>(); la clase de nivel básico que desciende de Object debe llamar al base.MemberwiseClone; todas las otras clases deben usar base.BaseClone<T> para obtener la nueva instancia y luego reemplazar cualquier campo clonable mutable con clones de los que están en el objeto original.

Yo también recomendaría la definición de los siguientes interfaces:

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

que permitirá situaciones en las que una clase puede tener algunos descendientes que pueden ser clonados y algunos que no pueden. Aquellos que pueden ser clonados pueden exponer los métodos públicos de clonación (que deben encadenarse al BaseClone<theirOwnType>). Los métodos que necesitan derivados clonables del tipo base pueden usar parámetros del tipo ICloneable<theBaseType>; esto les permitirá aceptar cualquier derivado clonable del tipo base, incluso si no todos los derivados comparten una clase base común.

Cuestiones relacionadas