`

c#深拷贝与浅拷贝

    博客分类:
  • C#
阅读更多

浅拷贝(影子克隆):只复制对象的基本类型,对象类型,仍属于原来的引用.
深拷贝(深度克隆):不紧复制对象的基本类型,同时也复制原对象中的对象.就是说完全是新对象产生的.

浅拷贝和深拷贝之间的区别:浅拷贝是指将对象中的值类型的字段拷贝到新的对象中,而对象中的引用型字段则指复制它的一个引用到目标对象。如果改变目标对象中引用型字段的值他将反映在原始对象中,也就是说原始对象中对应的字段也会发生变化。深拷贝与浅拷贝不同的是对于引用的处理,深拷贝将会在新对象中创建一个新的和原是对象中对应字段相同(内容相同)的字段,也就是说这个引用和原是对象的引用是不同的,我们在改变新对象中的这个字段的时候是不会影响到原始对象中对应字段的内容。所以对于原型模式也有不同的两种处理方法:对象的浅拷贝和深拷贝。

 

MemberwiseClone 方法创建一个浅表副本,方法是创建一个新对象,然后将当前对象的非静态字段复制到该新对象。如果字段是值类型的,则对该字段执行逐位复制。如果字段是引用 类型,则复制引用但不复制引用的对象;因此,原始对象及其复本引用同一对象。深拷贝,即实现ICloneable接口.ICloneable可用于深拷贝 和浅拷贝

 

这些都是概念,但是需要我们理解,下面介绍实例:

 

    浅拷贝示例:

 public class Client
    {
        static void Main(string[] args)
        {
            Person p1 = new Person(1, "Scoot", new Car("宝马"));

            Person p2 = p1.Clone() as Person;

            Console.Write("P1对象原始的值:");
            Console.WriteLine("id:{0},name:{1},car:{2}", p1.id, p1.name, p1.car.name);

            Console.WriteLine("改变P1的值后:");
            p1.id = 2;
            p1.name = "Lacy";
            p1.car.name = "红旗";

            Console.Write("P1对象的值:");
            Console.WriteLine("id:{0},name:{1},car:{2}", p1.id, p1.name, p1.car.name);
            Console.WriteLine();
            Console.Write("P2对象的值:");
            Console.WriteLine("id:{0},name:{1},car:{2}", p2.id, p2.name, p2.car.name);

            Console.ReadKey();
            /*浅拷贝的例子从得到的结果我们可以发现:
            值类型拷贝的是值而引用类型则拷贝引用(地址)
            那么当p1的对象中的引用类型的值改变时,p2对象中所引用
            类型的值也将发生改变
            */

        }
    }

    class Car
    {
        public string name;
        public Car(string name)
        {
            this.name = name;

        }
    }

    class Person
    {
        public int id;
        public string name;
        public Car car;
        public Person(int id, string name, Car car)
        {
            this.id = id;
            this.name = name;
            this.car = car;
        }

        //对外提供一个创建自身的浅副本的能力
        public object Clone()
        {
            return this.MemberwiseClone();
        }
    }

  

    浅拷贝示例:

using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication1
{
    public class Client
    {
        static void Main(string[] args)
        {
            Person p1 = new Person(1, "Scoot", new Car("宝马"));

            Person p2 = p1.Clone() as Person;

            Console.Write("P1对象原始的值:");
            Console.WriteLine("id:{0},name:{1},car:{2}", p1.id, p1.name, p1.car.name);

            Console.WriteLine("改变P1的值后:");
            p1.id = 2;
            p1.name = "Lacy";
            p1.car.name = "红旗";

            Console.Write("P1对象的值:");
            Console.WriteLine("id:{0},name:{1},car:{2}", p1.id, p1.name, p1.car.name);
            Console.WriteLine();
            Console.Write("P2对象的值:");
            Console.WriteLine("id:{0},name:{1},car:{2}", p2.id, p2.name, p2.car.name);

            Console.ReadKey();
        }
    }

    class Car
    {
        public string name;
        public Car(string name)
        {
            this.name = name;
        }
    }

    class Person : ICloneable //深拷贝必须实现ICloneable接口..
    {
        public int id;
        public string name;
        public Car car;
        public Person(int id, string name, Car car)
        {
            this.id = id;
            this.name = name;
            this.car = car;
        }

        //深拷贝
        public object Clone()
        {
            return this.MemberwiseClone() as Person;
        }
    }


}

 

 

   小结:

   浅拷贝:
   1.值类型:将对象中的数值类型的字段拷贝到新的对象中,        
   2.引用类型:对象中的引用型字段则指复制它的一个引用到目标对象。
    所以如果改变目标对象中引用型字段的值他将反映在原是对象中,

    深拷贝:
    1.值类型:和浅拷贝相同
    2.引用类型:拷贝对象应用,也拷贝对象实际内容,也就是创建了一个新的
    改变新对象 不会影响到原始对象的内容  
    这种情况需要为其实现ICloneable接口中提供的Clone方法。

 

   数组:

  //数组的复制(直接拷贝),也就是引用传递,指向的是同一个地址:

            int[] num = { 2, 3, 4, 5 };

            int[] numCopy = num;

            num[2] = 0;

            Console.WriteLine("num[2]=" + num[2]);
            Console.WriteLine("numCopy[2]=" + numCopy[2]);

            Console.ReadKey();

    浅拷贝:(值类型)

   

 //以下的CopyTo(),Copy(),Clone()方法也都是浅拷贝
            //由于该数组的元素是值类型,
            //所以是按值拷贝的 而不是按引用拷贝就如按值传递一样
            //所以改变新对象中的值,不会影响到源对象;        

            //CopyTo()方法
            int[] num = { 1, 2, 3, 4, 5 };

            int[] newArray = new int[5];

            num.CopyTo(newArray, 0);

            newArray[2] = 0;

            Console.WriteLine("num[2]=" + num[2]);

            Console.WriteLine("newArray[2]=" + newArray[2]);

            //Copy()方法
            int[] chenArray = new int[5];

            Array.Copy(num, chenArray, num.Length);

            chenArray[2] = 0;

            Console.WriteLine("num[2]=" + num[2]);

            Console.WriteLine("chenArray[2]=" + chenArray[2]);

            //Clone()方法
            int[] aArray = num.Clone() as int[];

            aArray[2] = 0;

            Console.WriteLine("num[2]=" + num[2]);

            Console.WriteLine("aArray[2]=" + aArray[2]);

            //字符串数组的浅拷贝
            //字符串对象是“不可变的”,即它们一旦创建就无法更改.
            //对字符串进行操作的方法实际上返回的是新的字符串对象.
            //所以newStr[2]改变不会影响到str[2]
            string[] str = new string[] { "aaa", "bbb", "ccc", "ddd" };

            String[] newStr = new String[4];

            str.CopyTo(newStr, 0);

            newStr[2] = "呆瓜";

            Console.WriteLine("str[2]=" + str[2]);

            Console.WriteLine("newStr[2]=" + newStr[2]);

            Console.ReadKey();

 

   特别说明:

  字符串在C#中是引用类型

 

class MyClass
{
  static void Main()
  {
    string s1 = "hello";

    string s2 = s1;

    s1 = "world";

    System.Console.WriteLine("s1:{0}\ns2:{1}",s1,s2);
  }
}

  

 你觉得运行结果是什么?是不是s2应该随s1一起变.

 运行结果为:

 s1:world
 s2:hello

 

 字符串是引用类型,为什么会出现这样的结果.MSDN上这样解释:

 

字符串对象是“不可变的”,即它们一旦创建就无法更改。对字符串进行操作的方法实际上返回的是新的字符串对象。

因此,上例中,string s2=s1;语句将会使s1 ,s2指向同一内存位置.如果改变s1(s1="world"),原来的"hello"并不会改  变,只是会创建新的字符串对象"world",s1对其引用.

  附个MSDN上的例子:

string s1 = "orange";
            string s2 = "red";
            s1 += s2;
            Console.WriteLine(s1);
            Console.ReadKey();

  示例中,将 s1 和 s2 的内容连接起来以构成一个字符串时,包含 "orange" 和 "red" 的两个字符串均保持不变。

 += 运算符会创建一个包含组合内容的新字符串。 结果是 s1 现在引用一个完全不同的字符串。只包含"orange"的字符

串仍然存在,但连接 s1 后将不再被引用。因此,出于性能方面的原因,大量的连接或其他涉及字符串的操作应当用 StringBuilder 类执行.

 

   浅拷贝:(引用类型)

 //这个时候数组中的元素是引用类型
        //在进行拷贝的时候,复制的是它的一个引用到目标对象
        //所以改变新拷贝的对象的值,改变会反应到源对象中 
public class Client
    {
        static void Main(string[] args)
        {
            Test[] TestArray = 
            { 
                new Test("张三"),
                new Test("李四"),
                new Test("王五")
            };

            Test[] newTest = new Test[3];

            TestArray.CopyTo(newTest, 0);
            //改变新对象的值源对象中的值也被会改变
            newTest[2].Name = "呆瓜";

            Console.WriteLine(newTest[2].Name);
            Console.WriteLine(TestArray[2].Name);

            Console.ReadKey();
        }

        class Test
        {
            private string name;

            public Test(string name)
            {
                this.name = name;
            }

            public string Name
            {
                get { return name; }
                set { name = value; }
            }

        }
    }

 

分享到:
评论

相关推荐

    C#浅拷贝深拷贝

    在C#编程中,浅拷贝(Shallow Copy)和深拷贝(Deep Copy)是两种不同的对象复制方式,它们涉及到内存管理和数据复制的细节。理解这两种拷贝机制对于优化代码性能和确保程序的正确性至关重要。 首先,我们来解释...

    c# 深拷贝与浅拷贝的区别分析及实例

    在C#编程中,了解深拷贝和浅拷贝的概念是非常重要的,特别是在处理复杂的数据结构时。这两种拷贝方式主要涉及到对象的复制行为,尤其是在内存管理和数据一致性方面。 浅拷贝,也称为影子克隆,它仅仅复制对象的基础...

    C#中的浅拷贝和深拷贝

    ### C#中的浅拷贝与深拷贝 在C#编程语言中,对象的复制是一项基本而重要的操作。根据复制的方式不同,可以分为浅拷贝(Shallow Copy)和深拷贝(Deep Copy)。这两种复制方式各有其特点和适用场景。 #### 值类型...

    C#浅拷贝(MemberwiseClone等多种方法)与深拷贝(反射、多种反序列化)实例

    在C#编程中,对象的复制是一个常见的操作,主要分为浅拷贝和深拷贝两种。浅拷贝只复制对象的引用,而深拷贝则会创建一个全新的对象,包括对象内部的所有引用对象。本文将深入探讨这两种拷贝方式以及它们在C#中的实现...

    C#浅拷贝和深拷贝数据【可联系作者购买】

    C#浅拷贝和深拷贝数据

    浅谈C#中ListT对象的深度拷贝问题

    一、List对象中的T是值类型的情况(int 类型等) 对于值类型的List直接用以下方法就可以复制: List<T> oldList = new List(); oldList.Add(..); List<T> newList = new List(oldList); 二、List对象中的T是引用...

    C# Lambda快速深度拷贝

    今天上班在班车上和一个同事讨论有关C#拷贝效率的问题,聊到了多种深度拷贝方法,其中就提到了一种Lambda表达式拷贝的方法,这位同事说这种深度拷贝快是快但是如果对象里面再嵌入对象就不能深度拷贝了,只进行浅拷贝...

    简单谈谈C#中深拷贝、浅拷贝

    在C#编程中,深拷贝和浅拷贝是两种重要的对象复制机制,它们主要针对对象内部包含的值类型和引用类型字段的区别处理。这两者的主要差异在于如何处理对象内部的引用类型字段。 浅拷贝,通常是通过`Object....

    深拷贝浅拷贝.zip

    拷贝分为两种主要类型:浅拷贝(Shallow Copy)和深拷贝(Deep Copy)。本篇文章将深入探讨这两种拷贝方式,并通过实际的代码示例来展示它们的区别和实现。 浅拷贝是指创建一个新对象,这个新对象引用的是原始对象...

    一种c#深拷贝方式完胜java深拷贝(实现上的对比分析)

    与Java的`clone()`方法相比,C#的序列化方法更加通用,不需要每个类都实现特定的复制逻辑,但可能在性能上略逊色于手动实现的深拷贝。 总的来说,Java和C#在深拷贝的实现上有各自的特点。Java依赖于`Cloneable`接口...

    深复制,浅复制区别c#代码

    ### 深复制与浅复制在C#中的区别 #### 引言 在面向对象编程中,对象的复制是一项常见的需求。对象复制可以分为两种主要类型:浅复制(Shallow Copy)和深复制(Deep Copy)。这两种复制方式有着本质的区别,并且在...

    C# 控件拷贝

    4. **深拷贝与浅拷贝**:在某些情况下,可能需要考虑更深一层的拷贝,即拷贝控件的属性值。对于非引用类型的属性,这通常已经完成。但对于引用类型,如自定义对象,需要进行额外的处理以实现深拷贝。 动态UI生成是...

    C#深度拷贝克隆源码

    在C#中,有两种常见的拷贝方法:浅拷贝和深拷贝。浅拷贝只复制对象的引用,而深拷贝则复制对象本身及其所有嵌套对象。对于值类型,如int、double,它们是按值复制,所以浅拷贝和深拷贝没有区别。但对引用类型,如...

    winform 深拷贝的实现源码

    这时就需要通过深拷贝来确保新对象与原对象之间的独立性。 深拷贝的实现通常有以下几种策略: - **手动实现**:对于每一个可能包含引用类型的属性,都需要编写代码进行递归复制。 - **接口实现**:定义一个...

    C#拷贝文件简单实现方法

    本文实例讲述了C#拷贝文件简单实现方法。分享给大家供大家参考。具体分析如下: ... 您可能感兴趣的文章:C#中4种深拷贝方法介绍简单谈谈C#中深拷贝、浅拷贝C#实现屏幕拷贝的方法C#通过指针实现快速拷贝的方法

    浅拷贝和深拷贝深入理解(shallow copy VS deep copy)

    引言C#中有两种类型变量,一种 是值类型变量,一种是引用类型变量,对于值类型变量,深拷贝和前拷贝都是通过赋值操作符号(=)实现,其效果一致,将对象中的值类型的字段拷贝到新的对象中.这个很容易理解。 本文重点...

Global site tag (gtag.js) - Google Analytics