问题起源:

昨天被同事问到一个浅拷贝与深拷贝区别的问题,说实在的,记得在学校时在书在看过相关概念区别。
只是,那时的在校生,又有几个能对书本上那写的尽量让鬼都看不懂知识能清晰的理解呢。
工作后虽然也有用到Clone相关的内容,不过也仅是应用,基础的概念还是没去仔细的理解,以于后来DataTable内部那不深不浅的架构拷贝都混和这些概念混在一起了。

曾经的以为:

让得一年多以前,我去面试,被一个人问到浅拷贝与深拷贝区别,我答:浅拷贝就是拷贝就是拷贝架构,不包括值,深拷贝就是连值也一同拷贝。
当我答出这样错误的答案时,对方没有纠正,反而似乎对我的答案还挺满意的。
唉,面试管自己不懂还问我这问题,还让我一直以为到现在都是这个样。

同事的质问:

接着同事说它的示例里,发现值是有拷贝的,于是我意识到我的认知是有问题了,我重新百度了一下。
网上乱七杂八的答案,让我得一个模糊的似乎正确的答案:浅拷贝不拷贝内部类的对象

引申出的错乱:

接着同事的疑问更一度把我引向这个容易迷乱的错误深渊:浅拷贝是对引用类型拷贝地址,对值类型直接进行拷贝。

最后,为了解惑,还是用示例来说话了:

    class DemoClass : ICloneable
    {
        public int intValue = 1;
        public string strValue = "1";
        public PersonEnum pEnum = PersonEnum.EnumA;
        public PersonStruct pStruct = new PersonStruct();
        public Person pClass = new Person("1");
        public int[] pIntArray = new int[] { 1 };
        public string[] pArray = new string[] { "1" };
        #region ICloneable 成员

public DemoClass()
        {
            pStruct.StructValue = 1;
        }
        public object Clone()
        {
           return this.MemberwiseClone();
        }
        #endregion
    }

class Person
    {
        public string Name;

public Person(string name)
        {
            Name = name;
        }

}
    public enum PersonEnum
    {
        EnumA=1,
        EnumB=2
    }
    public struct PersonStruct
    {
      public  int StructValue;
    }

说明:

这里的示例,我用上了:
int
string
int[]
string[]
enum
struct
class
然后接下来会产生实例A和克隆实例B。
接着改变B的值,看A的值会不会被改变。

接下我们看main方法

        static void Main(string[] args)
        {
            Demo();
        }
        public static void Demo()
        {
            DemoClass A = new DemoClass();
            DemoClass B = (DemoClass)A.Clone();
            B.intValue = 2;
            Write(string.Format("        int->[A:{0}] [B:{1}]", A.intValue, B.intValue));
            B.strValue = "2";
            Write(string.Format("     string->[A:{0}] [B:{1}]", A.strValue, B.strValue));
            B.pEnum = PersonEnum.EnumB;
            Write(string.Format("       Enum->[A:{0}] [B:{1}]", (int)A.pEnum, (int)B.pEnum));
            B.pStruct.StructValue = 2;
            Write(string.Format("     struct->[A:{0}] [B:{1}]", A.pStruct.StructValue, B.pStruct.StructValue));
            B.pIntArray[0] = 2;
            Write(string.Format("   intArray->[A:{0}] [B:{1}]", A.pIntArray[0], B.pIntArray[0]));
            B.pStringArray[0] = "2";
            Write(string.Format("stringArray->[A:{0}] [B:{1}]", A.pStringArray[0], B.pStringArray[0]));
            B.pClass.Name = "2";
            Write(string.Format("      Class->[A:{0}] [B:{1}]", A.pClass.Name, B.pClass.Name));
            System.Console.Read();
        }
        static void Write(string msg)
        {
            System.Console.WriteLine(msg);
        }

说明:

我们通过改变B实例的值,然后打印出A和B的值看结果。

打印结果如下:

从最后输出的结果我们得知:

对于内部的Class的对象和数组,会Copy地址一份。[从而改变B时,A也被改变了]
而对于其它内置的int/string/Enum/struct/object类型,则进行值copy。

最后,我试着百度寻找浅拷贝最原生的定义,浅搜了一下找不到,那这个定义,就留给读者解答一下了。

接着,我顺手比较了一下浅拷贝和深拷贝的性能测试:

先在DemoClass加入一个函数:

public object CloneNew()
{
   return new DemoClass();
}

接着我们写示例代码比较:

        public static void Compare()
        {
            DemoClass baseClass = new DemoClass();

DateTime start = DateTime.Now;
            for (int i = 0; i < 1000000; i++)
            {
                DemoClass newClass = (DemoClass)baseClass.Clone();
            }
            TimeSpan ts = DateTime.Now - start;
            System.Console.WriteLine("浅拷贝:" + ts.Ticks);

DateTime start2 = DateTime.Now;
            for (int j = 0; j < 1000000; j++)
            {
                DemoClass newClass = (DemoClass)baseClass.CloneNew();
            }
            TimeSpan ts2 = DateTime.Now - start2;
            System.Console.WriteLine("深拷贝:" + ts2.Ticks);

System.Console.Read();
        }

最后得出结果:

看来直接用浅拷贝性能还不如直接返回一个new的对象。
同样的,用克隆返回object最后还得对类型转换进行一些开销,教人情何以堪!

附言:

这两天刚好感冒,插了这两篇解惑篇,都是临时插进来的的问题了,接下来会继续写 CYQ.Data 轻量数据层之路 框架 的相关文章。

转载于:https://www.cnblogs.com/cyq1162/archive/2010/09/05/1818413.html

C# 浅拷贝与深拷贝区别 解惑篇相关推荐

  1. C#浅拷贝与深拷贝区别

    也许会有人这样解释C# 中浅拷贝与深拷贝区别: 浅拷贝是对引用类型拷贝地址,对值类型直接进行拷贝. 不能说它完全错误,但至少还不够严谨.比如:string 类型咋说? 其实,我们可以通过实践来寻找答案 ...

  2. python赋值浅拷贝和深拷贝的区别_python赋值、浅拷贝、深拷贝区别

    在写Python过程中,经常会遇到对象的拷贝,如果不理解浅拷贝和深拷贝的概念,你的代码就可能出现一些问题.所以,在这里按个人的理解谈谈它们之间的区别. 一.赋值(assignment) 在<Py ...

  3. 引用拷贝、浅拷贝和深拷贝区别

    类型 拷贝一般分为二大类 引用拷贝 和 对象拷贝,我们通常讲的深拷贝和浅拷贝都属于对象拷贝. 引用拷贝 顾名思义,即是对引用地址的拷贝,说明引用地址一样,指向堆中的对象是同一个对象. 如果对一个对象进 ...

  4. 快速了解“浅拷贝”与“深拷贝”区别

    浅拷贝与深拷贝 拷贝对象是Java中经常遇见的问题,Java中存在两种数据类型,基础数据类型和引用数据类型 基础数据类型:字符串(string).数值(number).布尔值(boolean).und ...

  5. Python的复制、浅拷贝、深拷贝区别和代码说明

    Python赋值 总结 一.概念解读 赋值:旧瓶装旧酒 浅拷贝:新瓶装旧酒 深拷贝:新瓶装新酒 二.实例测试 测试方法 赋值 浅拷贝 深拷贝 附录:全代码 赋值.浅拷贝.深拷贝 总结 赋值: 新建一个 ...

  6. Interview:算法岗位面试—10.11下午—上海某公司算法岗位(偏机器学习,互联网数字行业)技术面试考点之XGBoost的特点、python的可变不可变的数据类型、赋值浅拷贝深拷贝区别

    ML岗位面试:10.11下午-上海某公司算法岗位(偏机器学习,互联网数字行业)技术面试考点之XGBoost的特点.python的可变不可变的数据类型.赋值浅拷贝深拷贝区别 Interview:算法岗位 ...

  7. C# 之String以及浅拷贝与深拷贝

    C# 之String以及浅拷贝与深拷贝  一.String到底是值类型还是引用类型 MSDN 中明确指出 String 是引用类型而不是值类型,但 String 表面上用起来却像是值类型,这又是什么原 ...

  8. Python 浅拷贝和深拷贝 - Python零基础入门教程

    目录 一.Python 浅拷贝和深拷贝前言 二.Python 普通的变量赋值 三.Python 浅拷贝和深拷贝 1.Python 浅拷贝 copy 2.Python 深拷贝 deepcopy 3.Py ...

  9. OpenCV学习笔记(六)——感兴趣区域ROI(浅拷贝与深拷贝的区别)

    目录 1 浅拷贝 2 深拷贝 示例代码 有时我们只对一张图像中的部分区域感兴趣,而原图像又比较大,如果带着非感兴趣区域一起处理会占用大量的内存,因次我们希望从原图像中截取部分图像后再进行处理.我们将这 ...

最新文章

  1. 181102 Python环境搭建(安装Sublime Text3)
  2. javascript --- 使用ajax与服务器进行通信
  3. js-cookie使用方法
  4. 【Construct Binary Tree from Inorder and Postorder Traversal】cpp
  5. centos修改磁盘uuid_为什么MySQL用uuid做主键会被骂?
  6. 基于生命周期理论的农业科学数据中心化管理模式
  7. 【英语学习】【Daily English】U03 Leisure Time L03 Hiking and camping are some of his favorites.
  8. RabbitMQ之五种消息模型
  9. 新手进阶:巧用 macOS 帮助菜单?
  10. Linux下的tar命令
  11. Opencv-获取两点之间距离
  12. influxdb java api使用_InfluxDB使用HTTP的API查询数据
  13. 线程基础 第一篇:线程的定义、状态、属性、简单实现线程
  14. 深度解析!短视频如何成为现象级产品
  15. [读书笔记]《番茄工作法图解:简单易行的时间管理方法》
  16. MATLAB 声音文件分析、处理。
  17. 判断元素是否为负无穷大numpy.isneginf()
  18. 机器学习之贝叶斯网络实践(举例)
  19. python公众号监控_Python-WXPY实现微信监控报警
  20. box-sizing: border-box;失效问题

热门文章

  1. 虚拟打印的实现-DDK部分
  2. ESFramework网络通信框架介绍之(2)――网络通信消息NetMessage
  3. oracle分区属于什么知识,详细讲解Oracle表分区的相关概念及其优点
  4. ImportError: /opt/ros/kinetic/lib/python2.7/dist-packages/cv2.so: undefined symbol: PyCObject_Type
  5. edge新版 能够正则式_Python爬虫七 数据提取之正则
  6. React App项目页面进出场动画
  7. Redis (error) NOAUTH Authentication required.解决方法
  8. 第九十六题(编写strcpy 函数)
  9. arm-linux-gcc/ld/objcopy/objdump参数总结【转】
  10. vsftp安装与配置(通过虚拟用户登录)