您的位置:首页 > 编程语言 > C#

c#中如何实现拷贝对象

2017-12-15 16:30 363 查看
大家都知道,在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);

     }

    }

   }

  }
哈哈,到此为止,问题终于解决了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: