C#中深拷贝实现

卷儿哥 2023年12月05日 510次浏览

《C#中深拷贝和浅拷贝的介绍与用法》

在System.Object类中,有一个受保护的方法object.MemberwiseClone(),这个方法实现了对象的复制。事实上,它所实现的就是我们所称的浅拷贝。

深拷贝:指的是拷贝一个对象时,不仅仅把对象的引用进行复制,还把该
对象引用的值也一起拷贝。这样进行深拷贝后的拷贝对象就和源对象互相独立,其中任何一个对象的改动都不会对另外一个对象造成影响。

浅拷贝:指的是拷贝一个对象时,仅仅拷贝对象的引用进行拷贝,但是拷贝对象和源对象还是引用同一份实体。此时,其中一个对象的改变都会影响到另一个对象。

类型基类System.Object已经为所有类型都实现了浅拷贝,类型所要做的就是公开一个复制的接口,而通常的,这个接口会借由实现ICloneable接口来实现。ICLoneable只包含一个Clone方法。该方法既可以被实现为浅拷贝也可以被实现为深拷贝,具体如何取舍需要根据具体类型的需求来决定。

using System;
namespace DeepCopy
{
    class Program
    {
        static void Main(string[] args)
        {
            // 定义原始对象
            DpCopy dc = new DpCopy();
            dc._i = 10;
            dc._a = new A();

            // 定义深拷贝对象
            DpCopy deepClone = (DpCopy)dc.Clone();
            // 定义浅拷贝对象
            DpCopy shadowclone = (DpCopy)dc.MemberwiseClone();
            // 深拷贝的复制对象将拥有自己的引用类型成员对象
            // 所以这里的赋值不会影响原始对象
            deepClone._a._s = "我是深拷贝的A";
            Console.WriteLine(dc);
            Console.WriteLine(deepClone);
            Console.WriteLine("\r\n");

            // 浅拷贝的复制对象共享原始对象的引用类型成员对象
            // 所以这里的赋值将影响原始对象
            shadowclone._a._s = "我是浅拷贝的A";
            Console.WriteLine(dc);
            Console.WriteLine(shadowclone);

            Console.ReadKey();
        }
    }

    public class DpCopy : ICloneable
    {
        public int _i = 0;
        public A _a = new A();
        public object Clone()
        {
            // 实现深拷贝
            DpCopy newDc = new DpCopy();
            // 重新实例化一个引用类型变量
            newDc._a = new A();
            // 给新引用类型变量的成员值
            newDc._a._s = _a._s;
            newDc._i = _i;
            return newDc;
        }

        // 实现浅拷贝
        public new object MemberwiseClone()
        {
            return base.MemberwiseClone();
        }

        /// <summary>
        /// 重写类的ToString()方法
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return "I的值为:" + _i.ToString() + ",A为:" + _a._s;
        }
    }

    /// <summary>
    /// 包含一个引用成员的类型
    /// </summary>
    public class A
    {
        public string _s = "我是原始A";
    }
}