• 小议.NET中的对象拷贝


     

    小议.NET中的对象拷贝

    引言:最近准备开始写探索设计模式系列之六原型模式,希望在春节前可以写完这篇文章。为了便于阐述,在这里先对.NET中的对象拷贝机制做一些总结。——写在Post100篇之际。

    概述

    .NET里面,如果需要实现对象拷贝功能,那么就要实现ICloneable接口。ICloneable接口中有一个Clone方法,可以在类中覆写实现自定义的拷贝方法。对象拷贝的实现方法有两种:浅拷贝(Shallow Copy)与深拷贝(Deep Copy)。

    浅拷贝与深拷贝

    浅拷贝是指当对象的字段值被拷贝时,字段引用的对象不会被拷贝。例如,如果一个对象有一个指向字符串的字段,并且我们对该对象做了一个浅拷贝,那么两个对象将引用同一个字符串。而深拷贝是对对象实例中字段引用的对象也进行拷贝的一种方式,所以如果一个对象有一个指向字符串的字段,并且我们对该对象做了一个深拷贝的话,我们将创建一个新的对象和一个新的字符串--新对象将引用新字符串。需要注意的是执行深拷贝后,原来的对象和新创建的对象不会共享任何东西;改变一个对象对另外一个对象没有任何影响。(出自《.NET框架程序设计(修订版)》,李建忠译)。简单地说,浅拷贝只复制顶级(Top-Level)对象,而深拷贝则复制对象及其子对象。

    示意图如下:

    代码说明

    下面给出浅拷贝与深拷贝的两个例子,例子使用了ICloneable接口。C#中的数组是引用型的变量,下面通过数组来进行演示:

    1.浅拷贝:

    using System;

    namespace CopyDemo

    {

        /// <summary>

        /// ShallowCopy

        /// </summary>

        public class ShallowCopy : ICloneable

        {

           public int[] s = {4,5,6,7};

     

           public Object Clone()

           {

               return this.MemberwiseClone();

           }

           public void Display()

           {

               foreach(int i in s)

               {

                  Console.Write( i + ", ");

               }

               Console.WriteLine();

           }

        }

     

        class Client

        {

           public static void Main(string[] args)

           {

               ShallowCopy obj1 = new ShallowCopy();

               ShallowCopy obj2 = (ShallowCopy)obj1.Clone();

               obj1.s[0] = 1;

     

               obj1.Display();

               obj2.Display();

               Console.ReadLine();

           }

        }

    }

    运行结果:

    1,5,6,7

    1,5,6,7

    ShallowCopy对象实现了一个浅拷贝,因此当对obj1进行拷贝时,其字段s并没有拷贝,这导致obj1obj2的字段s都指向了同一个s,因此,当修改了obj1s[0]后,obj2s[0]也发生了变化。

    2.深拷贝:
    using System;

    namespace CopyDemo

    {

        /// <summary>

        /// DeepCoyp

        /// </summary>

        public class DeepCopy : ICloneable

        {

            public int[] s = {4,5,6,7};

     

           // 默认构造函数

           public DeepCopy()

           {

           }

           // Clone方法调用的私有构造函数

           private DeepCopy(int[] s)

           {

               this.s = (int[])s.Clone();

           }

           public Object Clone()

           {

               // 构造一个新的DeepCopy对象

               return new DeepCopy(this.s);

           }

            public void Display()

           {

               foreach(int i in s)

               {

                  Console.Write( i + ", ");

               }

               Console.WriteLine();

           }

        }

     

        class Client

        {

           public static void Main(string[] args)

           {

               DeepCopy obj1 = new DeepCopy();

               DeepCopy obj2 = (DeepCopy)obj1.Clone();

               obj1.s[0] = 1;

     

               obj1.Display();

               obj2.Display();

     

               Console.ReadLine();

           }

        }

    }

    运行结果:

    1,5,6,7

    4,5,6,7

    这次在拷贝的时候,不但拷贝对象本身,连里面的数组字段一并拷贝。因此,最终打印出来的obj1dobj2不同。

    总结

    .NET中,由于提供了Icloneable接口,使得对象拷贝操作变得非常简单。

    支持TerryLee的创业产品Worktile
    Worktile,新一代简单好用、体验极致的团队协同、项目管理工具,让你和你的团队随时随地一起工作。完全免费,现在就去了解一下吧。
    https://worktile.com
  • 相关阅读:
    UVA 125 Numbering Paths
    UVA 515 King
    UVA 558 Wormholes
    UVA 10801 Lift Hopping
    UVA 10896 Sending Email
    SGU 488 Dales and Hills
    HDU 3397 Sequence operation
    数据库管理工具navicat的使用
    javascript封装animate动画
    关于webpack没有全局安装下的启动命令
  • 原文地址:https://www.cnblogs.com/Terrylee/p/312493.html
Copyright © 2020-2023  润新知