C#深度学习の----深拷贝与浅拷贝

本人在进行编程的时候遇到一个问题,要对一个绑定的依赖属性进行赋值,改变属性中的某一部分,绑定的目标上的所有值都发生了变化,着并不是我想要的,由此引出深浅拷贝的问题。(请加群交流:435226676)

  首先,讲到深浅拷贝,自然就有一个问题来了?什么是深拷贝,什么又是浅拷贝呢?下面就具体介绍下它们的定义。

  深拷贝:指的是拷贝一个对象时,不仅仅把对象的引用进行复制,还把该对象引用的值也一起拷贝。这样进行深拷贝后的拷贝对象就和源对象互相独立,其中任何一个对象的改动都不会对另外一个对象造成影响。举个例子,一个人叫张三,然后使用克隆技术以张三来克隆另外一个人叫李四,这样张三和李四就是相互独立的,不管张三缺胳膊还是李四少腿了都不会影响另外一个人。在.NET领域,值对象就是典型的例子,如int, Double以及结构体和枚举等。具体例子如下所示:

int source = 123;
//值类型赋值内部执行深拷贝
int copy = source;
//对拷贝对象进行赋值不会改变源对象的值
copy = 234;
//同样对源对象赋值也不会改变拷贝对象的值
source = 345;浅拷贝:指的是拷贝一个对象时,仅仅拷贝对象的引用进行拷贝,但是拷贝对象和源对象还是引用同一份实体。此时,其中一个对象的改变都会影响到另一个对象。例如,一个人一开始叫张三,后来改名字为张老三了,可是他们还是同一个人,不管张三缺胳膊还是张老三少腿,都反应在同一个人身上。在.NET中引用类型就是一个例子。如类类型。具体例子如下所示:
public class Person
    {
        public string Name { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Person sourceP = new Person() { Name = "张三" };
            Person copyP = sourceP; // 浅拷贝
            copyP.Name = "张老三"; // 拷贝对象改变Name值
            // 结果都是"张老三",因为实现的是浅拷贝,一个对象的改变都会影响到另一个对象
            Console.WriteLine("Person.Name: [SourceP: {0}] [CopyP:{1}]", sourceP.Name, copyP.Name);
            Console.Read();
        }
    }
综上:深拷贝和浅拷贝主要影响引用类型,引用类型浅拷贝,拷贝的是引用,深拷贝,拷贝的是实体,引用类型浅拷贝会改变源

浅拷贝的实现:System.Object.MemberwiseClone()方法,如果需要可以对其进行封装;引用类型=也是浅拷贝深拷贝的实现:反射(保存最初对象以保证不会相互引用)、反序列化、可视化树
        public static T DeepCopyWithReflection<T>(T obj)
        {
            Type type = obj.GetType();

            // 如果是字符串或值类型则直接返回
            if (obj is string || type.IsValueType) return obj;

            if (type.IsArray)
            {
                Type elementType = Type.GetType(type.FullName.Replace("[]", string.Empty));
                var array = obj as Array;
                Array copied = Array.CreateInstance(elementType, array.Length);
                for (int i = 0; i < array.Length; i++)
                {
                    copied.SetValue(DeepCopyWithReflection(array.GetValue(i)), i);
                }

                return (T)Convert.ChangeType(copied, obj.GetType());
            }

            object retval = Activator.CreateInstance(obj.GetType());

            PropertyInfo[] properties = obj.GetType().GetProperties(
                BindingFlags.Public | BindingFlags.NonPublic
                | BindingFlags.Instance | BindingFlags.Static);
            foreach (var property in properties)
            {
                var propertyValue = property.GetValue(obj, null);
                if (propertyValue == null)
                    continue;
                property.SetValue(retval, DeepCopyWithReflection(propertyValue), null);
            }

            return (T)retval;
        }
// 利用XML序列化和反序列化实现
        public static T DeepCopyWithXmlSerializer<T>(T obj)
        {
            object retval;
            using (MemoryStream ms = new MemoryStream())
            {
                XmlSerializer xml = new XmlSerializer(typeof(T));
                xml.Serialize(ms, obj);
                ms.Seek(0, SeekOrigin.Begin);
                retval = xml.Deserialize(ms);
                ms.Close();
            }

            return (T)retval;
        }

        // 利用二进制序列化和反序列实现
        public static T DeepCopyWithBinarySerialize<T>(T obj)
        {
            object retval;
            using (MemoryStream ms = new MemoryStream())
            {
                BinaryFormatter bf = new BinaryFormatter();
                // 序列化成流
                bf.Serialize(ms, obj);
                ms.Seek(0, SeekOrigin.Begin);
                // 反序列化成对象
                retval = bf.Deserialize(ms);
                ms.Close();
            }

            return (T)retval;
        }

        // 利用DataContractSerializer序列化和反序列化实现
        public static T DeepCopy<T>(T obj)
        {
            object retval;
            using (MemoryStream ms = new MemoryStream())
            {
                DataContractSerializer ser = new DataContractSerializer(typeof(T));
                ser.WriteObject(ms, obj);
                ms.Seek(0, SeekOrigin.Begin);
                retval = ser.ReadObject(ms);
                ms.Close();
            }
            return (T)retval;
        }

至于可视化树,基本就是wpf中新visil等

时间: 2024-08-25 18:22:55

C#深度学习の----深拷贝与浅拷贝的相关文章

IOS学习—深拷贝和浅拷贝

// // main.m // 深拷贝与浅拷贝 // // Created by on 15/4/10. // Copyright (c) 2015年 apple. All rights reserved. // #import <Foundation/Foundation.h> #import "Student.h" #import "GoodStudent.h" int main(int argc, const char * argv[]) { @a

Javascript学习之深拷贝和浅拷贝详解

在JavaScript 中,存在着这样的两种拷贝方式.分别是:深拷贝和浅拷贝,这两种拷贝在实际中非常的常见,如果读者是一个阅读源码的爱好者,相信多多少少对深拷贝和浅拷贝有所了解.本文和大家分享的就是深拷贝和浅拷贝相关内容,一起来看看吧,希望对大家 学习javascript有所帮助. 一.浅拷贝 浅拷贝在现实中最常见的表现在赋值上面,例如 <!DOCTYPE html> <html lang="en"> <head> <meta charset=

python学习系列--深拷贝和浅拷贝

概念 普通情下,复制一个对象是不会新开辟内存空间的,只是把新的对象名称指向原有的内存地址,这种操作其实不是算是拷贝,只是新的引用.把新的对象置于新的内存空间中,才是拷贝.在python中,深浅拷贝的区别实际上是拷贝的深度不同. 操作 常见的'='号就是一种拷贝方式.python在复制对象时实际上是调用copy模块的copy方法,即copy.copy().而使用deepcopy()函数操作就是深拷贝.对于字符串和数字来说,不管是深拷贝还是浅拷贝,都只是在原有内存地址上的新引用,所以是没有区别的.可

C++ Primer 学习笔记_20_类与数据抽象(6)_深拷贝与浅拷贝、空类与空数组

C++ Primer 学习笔记_20_类与数据抽象(6)_深拷贝与浅拷贝.空类与空数组 一.深拷贝与浅拷贝 浅拷贝:被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象.换而言之,浅拷贝仅仅复制所考虑的对象,而不复制它所引用的对象. 深拷贝:被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量.那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象.换而言之,深拷贝把要复制的对象所引用的对象都复制了一遍. 浅拷贝可

字典的深拷贝与浅拷贝

以前只知道用dict2 = dict1 来进行复制(备份),结果发现对dict2做增删改等操作时,dict1也会随之变化,反过来也这样.没有好好学习基础的我,自然在这里面吃了不少的亏... 下面我们来介绍一下python的深拷贝与浅拷贝: 1 #!/usr/bin/python 2 # -*- coding: UTF-8 -*- 3 4 dict1 = {'user':'runoob','num':[1,2,3]} 5 6 dict2 = dict1 # 浅拷贝: 引用对象 7 dict3 =

【JS】深拷贝与浅拷贝的区别,实现深拷贝的几种方法

如何区分深拷贝与浅拷贝,简单点来说,就是假设B复制了A,当修改A时,看B是否会发生变化,如果B也跟着变了,说明这是浅拷贝,拿人手短,如果A没变,那就是深拷贝,自食其力. 此篇文章中也会简单阐述到栈堆,基本数据类型与引用数据类型,因为这些概念能更好的让你理解深拷贝与浅拷贝. 我们来举个浅拷贝例子: let a=[0,1,2,3,4], b=a; console.log(a===b); a[0]=1; console.log(a,b); 嗯?明明b复制了a,为啥修改数组a,数组b也跟着变了,这里我不

C++文件头,命名空间,new和delete,内联函数,引用,函数重载,构造函数和析构函数,深拷贝和浅拷贝,explict,this指针

 目  录 1       开始学习C++.............................................................................................................. 4 1.1       C++的头文件.................................................................................................

深度学习斯坦福cs231n 课程笔记

前言 对于深度学习,新手我推荐先看UFLDL,不做assignment的话,一两个晚上就可以看完.毕竟卷积.池化啥的并不是什么特别玄的东西.课程简明扼要,一针见血,把最基础.最重要的点都点出来 了. cs231n这个是一个完整的课程,内容就多了点,虽然说课程是computer vision的,但80%还是深度学习的内容.图像的工作暂时用不上,我就先略过了. 突然发现这两个课程都是斯坦福的,牛校就是牛. 课程主页 http://vision.stanford.edu/teaching/cs231n

IOS中复制对象的用法及深拷贝和浅拷贝详解

亲爱的网友,我这里有套课程想和大家分享,如果对这个课程有兴趣的,可以加我的QQ2059055336和我联系. 课程内容简介 我们软件是基于移动设备的.所以我们必然的选择了安卓作为我们的开发工具.课程中,我们将简要的介绍Android的基本概念,然后进行我们的实战开发.在开发中,大家讲学习到基本的组件,适配UI,数据的存储,多线程下载,开机广播,闹钟提醒,短信发送等实际项目开发中碰到的有用的知识点.通过课程学习,让大家能够掌握Android软件开发的流程,注意点,及优化.帮助大家迅速的掌握Andr