Deep Copy in C#

后端 未结 8 609
独厮守ぢ
独厮守ぢ 2021-02-05 20:36

MSDN gives this example of a deep copy (http://msdn.microsoft.com/en-us/library/system.object.memberwiseclone.aspx)

public class Person 
{
    public int Age;
           


        
相关标签:
8条回答
  • 2021-02-05 21:07

    The MemberwiseClone() creates a new instance of the class being copied, and also copies scalar fields into the corresponding members of the copy. It provides a better starting point for deep copying than just a plain new, because you need to "fix" only the items requiring deep copying.

    0 讨论(0)
  • 2021-02-05 21:08

    MemberwiseClone does create a new object and copies all non static fields. In case of reference types this means copying the references. So yes, after a member wise clone the fields of the new object point to the same objects as the fields of the original object (for reference types). That is why the example in the MSDN create a new instance of the IdInfo: To create a copy of that object as well.

    Your DeepCopy implementation is broken because it does not copy all fields, but if it would then the result would not be different from the MemberwiseClone solution.

    This question might also be an interesting read for you: Create a Deep Copy in C#

    0 讨论(0)
  • 2021-02-05 21:10

    Alternatively, if you are able to set Serializable attribute to all involved classes, you can use serialization. For the purpose of a generic deep copy I have this object extension method:

    public static class ObjectExtensions
    {
        #region Methods
    
        public static T Copy<T>(this T source)
        {
            var isNotSerializable = !typeof(T).IsSerializable;
            if (isNotSerializable)
                throw new ArgumentException("The type must be serializable.", "source");
    
            var sourceIsNull = ReferenceEquals(source, null);
            if (sourceIsNull)
                return default(T);
    
            var formatter = new BinaryFormatter();
            using (var stream = new MemoryStream())
            {
                formatter.Serialize(stream, source);
                stream.Seek(0, SeekOrigin.Begin);
                return (T)formatter.Deserialize(stream);
            }
        }
    
        #endregion
    }
    

    This should also copy your IdInfo field.

    Usage is simple:

    var copy = obj.Copy();
    
    0 讨论(0)
  • 2021-02-05 21:22

    The implementation of MemberwiseClone would do the following for your code.

    Person p = new Person();
    p.Age = this.Age;  // value copy
    p.Name = this.Name; // value copy
    p.IdInfo = this.IdInfo; // reference copy. this object is the same in both coppies.
    return p;
    
    0 讨论(0)
  • 2021-02-05 21:25

    In the example that you specified, the values of Age and Name would be zero/blank.

    This is due to the fact that you instantiate the Person object, but never set the values of these fields.

    From Object.MemberwiseClone Method

    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.

    So as you can see, using the MemberwiseClone method, your Age/Name fields will also be copied/cloned.

    0 讨论(0)
  • 2021-02-05 21:25

    Other alternative as object extension is the next:

    public static class ObjectExtension
    {
            public static T Copy<T>(this T lObjSource)
            {
                T lObjCopy = (T)Activator.CreateInstance(typeof(T));
    
                foreach (PropertyInfo lObjCopyProperty in lObjCopy.GetType().GetProperties())
                {
                    lObjCopyProperty.SetValue
                    (
                        lObjCopy,
                        lObjSource.GetType().GetProperties().Where(x => x.Name == lObjCopyProperty.Name).FirstOrDefault().GetValue(lObjSource)
                    );
                }
    
                return lObjCopy;
            }
    }
    

    For use:

    User lObjUserCopy = lObjUser.Copy();
    
    0 讨论(0)
提交回复
热议问题