大家都知道,在C#中变量的存储分为值类型和引用类型两种,而值类型和引用类型在数值变化是产生的后果是不一样的,值类型我们可以轻松实现数值的拷贝,那么引用类型呢,在对象拷贝上存在着一定的难度。

    下面我么从一个经典的例子谈起。
private void  doChange(string a)
  {
   int b = a;
   b = "2";
   System.Console.WriteLine(b);
   System.Console.WriteLine(a);
  }
当我么调用上面的函数doChange("1")以后,输出的结果是多少呢?很多大哥开到我提问这个问题,一定气得要骂街了,呵呵,很简单,输出结果是:
2
1
那么我们再看看下面的一个例子
public class data
  pubic string key ="1"
}
private void  doChange(data a)
  {
   data b = a;
   b.key = "2";
   System.Console.WriteLine(b.key.ToString());
   System.Console.WriteLine(a.key.ToString());
  }
我们再次调用doChange(new data),它的输出结果又是怎么样的呢?
有些人说:
2
1
如果你也是这么想的,那你就错了,呵呵!正确结果是……
2
2
为什么会是这样呢?很多人一定很奇怪,之所以会出现这样的问题,就和值类型和引用类型有关,第一个值函数的string 本身是个值类型,他在存储的时候,是直接开辟了一个存储空间,而第二个data类型的在存储的时候,其实是通过指针将变量和其存储空间链接在了一起,当声明data b=a时,就将b的指针指向了a的指针所指向的存储位置,而当将b.key="2"赋值后,其实是将b.key所指向的存储空间赋值"2",这个时候因为a和b的指针是指向同一个存储空间的,所以a.key和b.key的值同时变成了2。
    那么问题出现了,怎么才能使b和a不同时改变呢?有人会告诉我,你可以这样写呀!
private void  doChange(data a)
  {
   data b = new data();
   b = a;
   b.key = "2";
   System.Console.WriteLine(b.key.ToString());
   System.Console.WriteLine(a.key.ToString());
  }
正样,在new的时候,系统会为a和b开辟不同的两个存储空间,这样就不会出现上面的问题了。其实并不是这样的,当你new的时候,确实a和b是有不同的存储位置的,可以当你b=a的时候,其实又是将b的指针指向了a的存储位置上,而将b的存储位置进行了空闲,过不了多久,C#的垃圾回收机制会将b的存储空间进行回收。
    这下岂不坏了,当我么使用一个复杂的对象时候,怎么才能够使一个对象等于另一个对象,而在其中一个对象的属性值改变后,另一个对象的属性不会跟着改变呢?
    在C#中,有写系统对象提供了克隆方法,但是,对于用户自定义的对象是不存在这个方法的,我们要想实现克隆操作,必须手动去便利每一个属性,然后对属性进行赋值,也就是下面的方法。
private void  doChange(data a)
  {
   data b = new data();
   b.key = a.key;
   b.key ="2";
   System.Console.WriteLine(b.key.ToString());
   System.Console.WriteLine(a.key.ToString());
  }
这样对于属性很少的对象操作起来还算可以,但是对于属性很多的对象操作起来却相当麻烦,所以可以采用反射的机制,对每一个属性进行赋值,具体代码如下。
public static void CopyValue(object origin,object target)
  {
   System.Reflection.PropertyInfo[] properties = (target.GetType()).GetProperties();
   System.Reflection.FieldInfo[] fields = (origin.GetType()).GetFields();
   for ( int i=0; i< fields.Length; i++)
   {
    for ( int j=0; j< properties.Length; j++)
    {
     if (fields[i].Name == properties[j].Name && properties[j].CanWrite)
     {
      properties[j].SetValue(target,fields[i].GetValue(origin),null);
     }
    }
   }
  }
哈哈,到此为止,问题终于解决了。
 
借鉴自:http://blog.sina.com.cn/s/blog_4c8a4e5901009lya.html

C# 对象拷贝问题 =等同于浅拷贝的更多相关文章

  1. Python对象拷贝——深拷贝与浅拷贝

    对象赋值 浅拷贝 深拷贝 1. 对象赋值 对象的赋值实际上是对对象的引用.也就是说当把一个对象赋值给另一个对象时,只是拷贝了引用.如: >>> t1 = tuple('furzoom ...

  2. ObjectiveC中的赋值,对象拷贝,浅拷贝与深拷贝

    在开发过程中我们经常会遇到对象拷贝的问题,下面我们分别讨论赋值操作.对象拷贝.以及浅拷贝(Shallow copy)与深拷贝(Deep copy)的区别与各自的实现方式. 一.不同对象的赋值操作 Ob ...

  3. JavaScript 对象拷贝研究

    介绍一下JavaScript里面的一些对象拷贝的方法 浅拷贝 深拷贝 利用序列化进行对象拷贝

  4. iOS 深拷贝、浅拷贝、自定义对象拷贝简介

    copy语法的目的:改变副本的时候,不会影响到源对象: 深拷贝:内容拷贝,会产生新的对象.新对象计数器置为1,源对象计数器不变. 浅拷贝:指针拷贝,不会产生新的对象.源对象计数器+1. 拷贝有下面两个 ...

  5. python中的对象拷贝

    python中.进行函数參数传递或者返回值时,假设是一般的变量,会拷贝传递.假设是列表或字典则是引用传递.那python怎样对列表和字典进行拷贝传递呢:标准库的copy模块提供了两个方法:copy和d ...

  6. OC中对象拷贝概念

    OC中的对象拷贝概念,这个对于面向对象语言中都会有这种的问题,只是不同的语言有不同的解决方式:C++中有拷贝构造函数,Java中需要实现Cloneable接口,在clone方法中进行操作.但是不过OC ...

  7. 也说Javascript对象拷贝及疑问

    一.浅拷贝 当我们需要将一个对象拷贝至另一个对象时,我们一般会这么实现 function shadowCopy(source,target){ var target=target||{}; for(v ...

  8. Java Object 对象拷贝答疑

    Java Object 对象拷贝答疑 @author ixenos 摘要:在对象的clone过程需要注意的几点.关于关键字this.super 关于clone[对象拷贝] 在实际编程过程,有时候我们会 ...

  9. Java Object 对象拷贝

    Java Object 对象拷贝 @author ixenos JAVA 对象拷贝 Java里的clone分为:  1.浅拷贝:浅复制仅仅复制所考虑的对象,而不复制它所引用的对象,Object类里的c ...

随机推荐

  1. Fidder 工具使用

    Fiddler是最强大最好用的Web调试工具之一,它能记录所有客户端和服务器的http和https请求,允许你监视,设置断点,甚至修改输入输出数据. 使用Fiddler无论对开发还是测试来说,都有很大 ...

  2. Linux SSH 互信

    第一步: 创建用于身份认证的两个密钥文件 ssh-keygen #注明.想省事的话打完这个命令后一直回车就行了. 第二步: 把公钥上传到目标主机上去 ssh-copy-id -i id_rsa.pub ...

  3. oracle 查询表的大小,表空间的使用情况,默认表空间

    oracle 查询表的大小,表空间的使用情况,默认表空间 oracle 查询表的大小,表空间的使用情况,默认表空间 --查看某张表占用磁盘空间大小 ( 表名大写 ) Select Segment_Na ...

  4. chrome调试ajax

    network可以查看ajax的信息.非常的实用.

  5. Microsoft Azure 大计算 – 宣布收购 GreenButton

     数据以及令人不可思议的计算能力,正在改变我们日常业务的经营方式,从科学和工程到媒体和金融,各行各业的客户正逐渐意识到什么是可能的.我们对整个基因组进行分析,以研制新药物.我们构建金融和保险模型, ...

  6. iOS 4.2 SDK安装

    iOS 4.2 SDK安装 ◆系统版本:10.6.5 ◆硬件配置: ◆10G空间,3.5G内存,显卡:GMA950 Xcode 3.2.5和iOS 4.2 SDK下载:http://developer ...

  7. openstack core components use 总结

    1,附加volume(块存储,云硬盘)到vmInstances(虚拟机实列)

  8. jQuery $.each用法比较详细了

    以下内容非原创,来自百度文库http://wenku.baidu.com/view/4796b6145f0e7cd18425368e.html 通过它,你可以遍历对象.数组的属性值并进行处理. 使用说 ...

  9. 加入收藏夹的js代码(求兼容chrome浏览器的代码)

    从网上找了加入收藏夹的js代码,但不兼容chrome,不知道有没有兼容chrome的相关代码,希望有知道的告诉一下,谢谢! 代码如下 $("#id").click(function ...

  10. Codeforces Round #277.5 (Div. 2)-D

    题意:求该死的菱形数目.直接枚举两端的点.平均意义每一个点连接20条边,用邻接表暴力计算中间节点数目,那么中间节点任选两个与两端可组成的菱形数目有r*(r-1)/2. 代码: #include< ...