C#中深复制的实现

浅复制

object对象中以定义了MemberwiseClone()方法来实现浅复制,我们只需调用该方法即可(注意:该方法访问控制为protected)

C#中深复制的实现_第1张图片

class Program
{
    public static void Main(string[] args)
    {
        var classA1 = new ClassA
        {
            a = 1,
            b = "haha",
            d = new ClassB{ c ="haha" }
        };

        var classA2 = (ClassA)classA1.Clone();

        classA2.b = "xixi";
        classA2.d.c = "xixi";
        Console.WriteLine("classA1.b=" + classA1.b + "\nclassA2.b=" + classA2.b);
        Console.WriteLine("classA1.d.c=" + classA1.d.c + "\nclassA2.d.c=" + classA2.d.c);
    }

    public class ClassA : ICloneable
    {
        public int a;

        public string b;

        public ClassB d;


        public object Clone()
        {
            return MemberwiseClone();
        }
    }

    public class ClassB
    {
        public string c;
    }
}

输出结果:

classA1.b=haha
classA2.b=xixi
classA1.d.c=xixi
classA2.d.c=xixi

这里有个问题:string也是引用类型,更改使用浅复制的到classA2对象的b的值后,为什么classA1对象的b的值为什么没有跟着变化?

知识点:C#中字符串的值是不可修改的,执行修改字符串的操作时,会重新创建一个新的string对象,然后让变量指向新对象的地址。

深复制

  • 通过序列化实现
//只需修改Clone方法的实现,同时使用[Serializable]标记ClassA类和ClassB类为可序列化,其他部分不变
[Serializable]
public class ClassA : ICloneable
{
    public int a;

    public string b;

    public ClassB d;


    public object Clone()
    {
        using (MemoryStream stream = new MemoryStream(1000))
        {
            BinaryFormatter formatter = new BinaryFormatter();
            formatter.Serialize(stream, this);
            stream.Seek(0, SeekOrigin.Begin);
            return formatter.Deserialize(stream);
        }
    }
}

[Serializable]
public class ClassB
{
    public string c;
}
  • 通过Json实现
using Newtonsoft.Json;

public object Clone()
{
    var str = JsonConvert.SerializeObject(this).ToString();
    return JsonConvert.DeserializeObject(str);
}

相比于序列化,使用Json的方式不用给每个用到的类添加[Serializable]标记(修改原类),且更简洁

你可能感兴趣的:(.NET)