我想要一份真正的深度拷贝。在Java中,这很容易,但在c#中如何做到呢?


当前回答

重要提示

BinaryFormatter已弃用,2023年11月后将不再在. net中使用。参见BinaryFormatter废弃策略


我已经看到了一些不同的方法,但我使用一个通用的实用方法:

public static T DeepClone<T>(this T obj)
{
 using (var ms = new MemoryStream())
 {
   var formatter = new BinaryFormatter();
   formatter.Serialize(ms, obj);
   ms.Position = 0;

   return (T) formatter.Deserialize(ms);
 }
}

注:

你的类必须被标记为[Serializable]才能工作。 您的源文件必须包括以下代码: 使用System.Runtime.Serialization.Formatters.Binary; 使用先;

其他回答

重要提示

BinaryFormatter已弃用,2023年11月后将不再在. net中使用。参见BinaryFormatter废弃策略


我已经看到了一些不同的方法,但我使用一个通用的实用方法:

public static T DeepClone<T>(this T obj)
{
 using (var ms = new MemoryStream())
 {
   var formatter = new BinaryFormatter();
   formatter.Serialize(ms, obj);
   ms.Position = 0;

   return (T) formatter.Deserialize(ms);
 }
}

注:

你的类必须被标记为[Serializable]才能工作。 您的源文件必须包括以下代码: 使用System.Runtime.Serialization.Formatters.Binary; 使用先;

MSDN文档似乎暗示Clone应该执行深度复制,但它从未明确说明:

ICloneable接口包含一个成员,克隆,它的目的是支持克隆超出MemberWiseClone提供的克隆…

你会发现我的帖子很有帮助。

http://pragmaticcoding.com/index.php/cloning-objects-in-c/

最好的方法是:

    public interface IDeepClonable<T> where T : class
    {
        T DeepClone();
    }

    public class MyObj : IDeepClonable<MyObj>
    {
        public MyObj Clone()
        {
            var myObj = new MyObj();
            myObj._field1 = _field1;//value type
            myObj._field2 = _field2;//value type
            myObj._field3 = _field3;//value type

            if (_child != null)
            {
                myObj._child = _child.DeepClone(); //reference type .DeepClone() that does the same
            }

            int len = _array.Length;
            myObj._array = new MyObj[len]; // array / collection
            for (int i = 0; i < len; i++)
            {
                myObj._array[i] = _array[i];
            }

            return myObj;
        }

        private bool _field1;
        public bool Field1
        {
            get { return _field1; }
            set { _field1 = value; }
        }

        private int _field2;
        public int Property2
        {
            get { return _field2; }
            set { _field2 = value; }
        }

        private string _field3;
        public string Property3
        {
            get { return _field3; }
            set { _field3 = value; }
        }

        private MyObj _child;
        private MyObj Child
        {
            get { return _child; }
            set { _child = value; }
        }

        private MyObj[] _array = new MyObj[4];
    }
    public static object CopyObject(object input)
    {
        if (input != null)
        {
            object result = Activator.CreateInstance(input.GetType());
            foreach (FieldInfo field in input.GetType().GetFields(Consts.AppConsts.FullBindingList))
            {
                if (field.FieldType.GetInterface("IList", false) == null)
                {
                    field.SetValue(result, field.GetValue(input));
                }
                else
                {
                    IList listObject = (IList)field.GetValue(result);
                    if (listObject != null)
                    {
                        foreach (object item in ((IList)field.GetValue(input)))
                        {
                            listObject.Add(CopyObject(item));
                        }
                    }
                }
            }
            return result;
        }
        else
        {
            return null;
        }
    }

这种方式比BinarySerialization快几倍,而且不需要[Serializable]属性。

基于Kilhoffer的解决方案……

在c# 3.0中,你可以像下面这样创建一个扩展方法:

public static class ExtensionMethods
{
    // Deep clone
    public static T DeepClone<T>(this T a)
    {
        using (MemoryStream stream = new MemoryStream())
        {
            BinaryFormatter formatter = new BinaryFormatter();
            formatter.Serialize(stream, a);
            stream.Position = 0;
            return (T) formatter.Deserialize(stream);
        }
    }
}

用DeepClone方法扩展任何标记为[Serializable]的类

MyClass copy = obj.DeepClone();