C#实现拷贝对象

大家都知道,在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);
     }
    }
   }
  }

时间: 2024-11-07 12:56:06

C#实现拷贝对象的相关文章

Python 拷贝对象(深拷贝deepcopy与浅拷贝copy)

http://www.jb51.net/article/15714.htm 1. copy.copy 浅拷贝 只拷贝父对象,不会拷贝对象的内部的子对象.2. copy.deepcopy 深拷贝 拷贝对象及其子对象 一个很好的例子: 1 import copy 2 a = [1, 2, 3, 4, ['a', 'b']] #原始对象 3 4 b = a #赋值,传对象的引用 5 c = copy.copy(a) #对象拷贝,浅拷贝 6 d = copy.deepcopy(a) #对象拷贝,深拷贝

objective-c copy mutableCopy 拷贝对象

原来不是所有的对象都支持 copy 只有遵守NSCopying 协议的类才可以发送copy消息 只有遵守NSMutableCopying 协议的类才可以发送mutableCopy消息 假如发送了一个没有遵守上诉两协议而发送 copy或者 mutableCopy,那么就会发生异常 默认 nsobject没有遵守这两个协议 但是 copy和mutableCopy这两个方法是nsobject定义的 如果想自定义一下copy 那么就必须遵守NSCopying,并且实现 copyWithZone: 方法

使用copy来拷贝对象

拷贝对象 您通过将 copy 消息发送给对象,以制作对象的副本. NSArray *myArray = [yourArray copy]; 要拷贝,接收对象的类必须遵守 NSCopying 协议.如果想要对象可供拷贝,必须采用并实施此协议的 copy 方法. 有时,当您想要确保对象的状态在使用时不会更改,会拷贝从程序的其他地方获取的对象. 拷贝行为是特定于某一个类的,具体取决于实例的特定性质.大多数类实现深拷贝,即复制所有实例变量和属性:部分类(如集类)实现浅拷贝,即仅复制对这些实例变量和属性的

夺命雷公狗—angularjs—23—copy拷贝对象

copy这在angularjs中是一个拷贝对象的方法: <!DOCTYPE html> <html lang="en" ng-app="myapp"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="js/angular.min.js"></script>

Java 使用反射拷贝对象一般字段值

在<Java解惑>上面看到第八十三例--诵读困难者,要求使用非反射实现单例对象的拷贝.查阅了部分资料,先实现通过反射拷贝对象. 1. 编写需要被拷贝的对象Person package com.scl.j2se.reflectjavabean; public class Person { public String getName() { return name; } public void setName(String name) { this.name = name; } public St

Item 12:完整地拷贝对象(拷贝构造函数、复制运算符) Effective C++笔记

Item 12: Copy all parts of an object 在一个成熟的面向对象的C++系统中,只有两种拷贝对象的方式:复制构造函数和赋值运算符, 不妨称他们为拷贝函数. 拷贝函数属于编译器默认生成的函数(参考:Item 5:那些被C++默默地声明和调用的函数), 默认的拷贝函数确实会完整地拷贝对象,但有时我们选择重载拷贝函数,问题就出在这里! 一个正确拷贝函数的实现是这样的: class Customer{ string name; public: Customer::Custo

拷贝对象属性

        /**  * 拷贝属性到目标对象,如果为空不拷贝,目标对象属性有值,则不拷贝该属性  *   * @param source  *            待拷贝属性的对象  * @param target  *            目标对象  * @throws BeansException  */ public static void copyPropertiesExclude(Object source, Object target) throws BeansExcepti

关于js拷贝对象的问题

在使用vue的时候遇到一个需求需要备份一个多维数组对象,用了好几种方法得到的结果都是相互连带影响的,无法做到在修改原数组的基础上,copy出一份为改动过的原数据,看了下网上各路大仙的套路,还是不能深信,还是自己动手看看最好了. 首先是例子1,假如是一个单纯简单的数组对象: // ------------情况1------------ var arr = [0,1,2,3]; var arr1 = arr; var arr2 = arr.slice(0); var arr3 = JSON.pars

简单的拷贝对象类

public static class TypeHelper { public static TP AutoCopy<TP, TC>(TC source) where TP : new() { TP dest = new TP(); var ParentType = typeof(TP); var Properties = ParentType.GetProperties(); foreach (var Propertie in Properties) { if (Propertie.CanR