拷贝对象的三种方式

来源:百度文库 编辑:神马文学网 时间:2024/04/29 21:57:21

对象拷贝又叫对象克隆或对象复制,要求在不影响原对象及其内容的情况下,产生该对象的一个副本并顺利工作。对象克隆一般用于把对象初始化为默认状态。根据这几天的观察,共总结出三种对象拷贝的方法,下面分别介绍。
在介绍之前,首先要分清浅拷贝和深拷贝之间的区别。所谓浅拷贝,是指拷贝了对象整体的引用或者对象内部某些引用类型的引用,而非引用类型的属性则拷贝其值。这么说有些抽象,举个例子,假如对象objA(A类的一个实例)有一个属性是objB(B类的一个实例,是引用类型),如果浅拷贝objA到另外一个A类的实例,那么只是拷贝了objB的引用,而没有拷贝其值(当然值也一样),其他的非引用类型的属性,则直接拷贝值。浅拷贝拷贝的“量”感觉较少,因为只是拷贝了引用类型的引用而没有拷贝其值,这样反而让两对象之间的联系更加紧密,只要有一个对象的某个引用类型的属性变化,都会使另外一个对象发生同样的变化,但值类型的却不会这样,因为它只是拷贝了值。当然,如果你为了图省事,直接把objA以赋值的形式赋给了另外一个对象,那么本身就是拷贝了这个对象的引用(对象是引用类型),对象内所有属性,无论是引用类型还是值类型,只要有一个对象发生变化,另外一个对象都会发生变化,因为两个对象指向了同一地址,所以内部属性当然也指向了统一地址。与浅拷贝不同,深拷贝只是拷贝了objA的属性的值,即使属性属于引用类型,也不会拷贝引用,只是拷贝它的值!于是,两个对象没有任何关系,改动其中一个,不会对另外一个产生影响。
第一种方法:对象间的直接赋值
用“=”给两个对象赋值,这是我们经常用到的,但这不是一种好习惯,因为这样属于绝对的浅拷贝,两个对象指向同一地址,共同变化。
Eg,假如有一个Teacher类,然后
Teacher teaTest1 = new Teacher();
Teacher teaTest2 = teaTest1;//直接赋值
这样完成的直接赋值,teaTest1和teaTest2实际上是同一个对象,两对象指向同一地址,只要其中任何一个对象变化,都会引起另外一个的变化,无论什么属性。所以,这是一种绝对的浅拷贝方式。
第二种方法:对象属性间的赋值
第一种方法是用“=”给对象赋值,这次是用“=”给对象的属性赋值,这就存在这样一种问题,如果该属性是引用类型的,则其中一个对象该属性变化,一定会影响到另外一个对象的该属性,即两属性指向同一地址;如果该属性是值类型,则只是拷贝了该属性的值,其中一个对象该属性的变化,不再影响到另外一个对象该属性的值。
通常这种对属性的赋值,是在类的构造函数内实现的。Eg,部分属性的赋值,则用直接赋值,若所有属性都赋值,则可以使用反射机制来实现。
using System;
using System.Reflection;
namespace利用反射拷贝对象
{
    public enum InitializeMethods{PartInitialize,AllInitialize};//拷贝对象属性的全部还是部分
    public class Teacher
    {   private int intGrade;
        private int intSalary;
        private string strDept = string.Empty;
 
        public int Grade{get{return this.intGrade;}set{this.intGrade = value;}}
        public int Salary{get{return this.intSalary;}set{this.intSalary = value;}}
        public string Dept{get{return this.strDept;}set{this.strDept = value;}}
        public Teacher()//构造函数1
        {
        }
        public Teacher(int grade,int salary,string dept)//构造函数2
        {
            this.intGrade = grade;
            this.intSalary = salary;
            this.strDept = dept;
        }
        public Teacher(Teacher teach,InitializeMethods initM)//构造函数3
        {
            if(initM == InitializeMethods.PartInitialize)//根据要求选择要拷贝的对象属性,这里选择了两个属性
            {
                this.intGrade = teach.intGrade;
                this.intSalary = teach.intSalary;
            }
            else
            if(initM == InitializeMethods.AllInitialize)//利用反射机制获得对象teach的所有属性信息并拷贝到另一个对象
            {
                System.Reflection.PropertyInfo[] pInfoArray = teach.GetType().GetProperties();
                foreach(PropertyInfo pInfoTmp in pInfoArray)
                {
                    object objMyValue = teach.GetType().InvokeMember(pInfoTmp.Name,BindingFlags.GetProperty,null,teach,null);
teach.GetType().InvokeMember(pInfoTmp.Name,BindingFlags.SetProperty,null,this,new object[]{objMyValue});
                }
            }
        }
    }
}
 
第三种方法:使用ICloneable接口进行深拷贝
Eg
 
using System;
 
namespace ICloneable接口的用途
{
    public class Women:ICloneable
    {
        public Women()
        {
        }
        public Women(string strN,int intA,Men menM)
        {
            this.strName = strN;
            this.intAge = intA;
            this.menMale = menM;
        }
        private string strName;
        private int intAge;
        private Men menMale;
        public string Name
        {
            set
            {this.strName = value; }
            get
            {return this.strName; }
        }
        public int Age
        {set
            {this.intAge = value; }
            get
            {return this.intAge; }
        }
        public Men Male
        {
            set
            {this.menMale = value; }
            get
            {return this.menMale; }
        }
        #region ICloneable 成员
 
        public object Clone()
        {return new Women(this.strName,this.intAge,this.menMale) as Women; }
//      public object Clone()//这个属于浅拷贝
//      {
//          return this.MemberwiseClone();
//      }
        #endregion
    }
}
使用时,Women womenTest 2= womenTest1.Clone();
        或者通过接口进行调用,更加有利于程序的整合。eg
        ICloneable pC = womenTest1;
              Women womenTest2 = pC.Clone();

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/suinon/archive/2008/06/20/2569093.aspx