程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C# 復制(深拷貝、淺拷貝),

C# 復制(深拷貝、淺拷貝),

編輯:C#入門知識

C# 復制(深拷貝、淺拷貝),


Object.MemberwiseClone 方法

創建當前 Object 的淺表副本。

protected Object MemberwiseClone()

MemberwiseClone 方法創建一個淺表副本,方法是創建一個新對象,然後將當前對象的非靜態字段復制到該新對象。 如果字段是值類型的,則對該字段執行逐位復制。 如果字段是引用類型,則復制引用但不復制引用的對象;因此,原始對象及其復本引用同一對象。

例如,考慮對象X引用對象 A 和 B , 對象 B 依次引用對象 C。 X 的淺表副本創建一個新對象 X2,該對象也引用對象 A 和 B。 相比而言,X 的深層副本創建一個新對象 X2,該對象引用新對象 A2 和 B2(分別為 A 和 B 的副本)。 B2 又引用新對象 C2,C2 是 C 的副本。 該示例闡釋了淺層和深層復制操作之間的區別。


有很多方法可以實現深層復制操作,前提是淺表復制操作由 MemberwiseClone 方法執行但不符合您的需求。

這些要求包括:

 下面的示例演示 MemberwiseClone 方法。 它定義了 ShallowCopy 方法,該方法通過調用 MemberwiseClone 方法來在 Person 對象上執行淺表復制操作。 它還定義了在 Person 對象上執行深層復制操作的DeepCopy 方法。

using System;

public class IdInfo
{
    public int IdNumber;

    public IdInfo(int IdNumber)
    {
        this.IdNumber = IdNumber;
    }
}

public class Person 
{
    public int Age;
    public string Name;
    public IdInfo IdInfo;

    public Person ShallowCopy()
    {
       return (Person)this.MemberwiseClone();
    }

    public Person DeepCopy()
    {
       Person other = (Person) this.MemberwiseClone(); 
       other.IdInfo = new IdInfo(this.IdInfo.IdNumber);
       return other;
    }
}

public class Example
{
    public static void Main()
    {
        // Create an instance of Person and assign values to its fields.
        Person p1 = new Person();
        p1.Age = 42;
        p1.Name = "Sam";
        p1.IdInfo = new IdInfo(6565);

        // Perform a shallow copy of p1 and assign it to p2.
        Person p2 = (Person) p1.ShallowCopy();

        // Display values of p1, p2
        Console.WriteLine("Original values of p1 and p2:");
        Console.WriteLine("   p1 instance values: ");
        DisplayValues(p1);
        Console.WriteLine("   p2 instance values:");
        DisplayValues(p2);

        // Change the value of p1 properties and display the values of p1 and p2.
        p1.Age = 32;
        p1.Name = "Frank";
        p1.IdInfo.IdNumber = 7878;
        Console.WriteLine("\nValues of p1 and p2 after changes to p1:");
        Console.WriteLine("   p1 instance values: ");
        DisplayValues(p1);
        Console.WriteLine("   p2 instance values:");
        DisplayValues(p2);

        // Make a deep copy of p1 and assign it to p3.
        Person p3 = p1.DeepCopy();
        // Change the members of the p1 class to new values to show the deep copy.
        p1.Name = "George";
        p1.Age = 39;
        p1.IdInfo.IdNumber = 8641;
        Console.WriteLine("\nValues of p1 and p3 after changes to p1:");
        Console.WriteLine("   p1 instance values: ");
        DisplayValues(p1);
        Console.WriteLine("   p3 instance values:");
        DisplayValues(p3);
    }

    public static void DisplayValues(Person p)
    {
        Console.WriteLine("      Name: {0:s}, Age: {1:d}", p.Name, p.Age);
        Console.WriteLine("      Value: {0:d}", p.IdInfo.IdNumber);
    }
}
// The example displays the following output:
//       Original values of p1 and p2:
//          p1 instance values:
//             Name: Sam, Age: 42
//             Value: 6565
//          p2 instance values:
//             Name: Sam, Age: 42
//             Value: 6565
//       
//       Values of p1 and p2 after changes to p1:
//          p1 instance values:
//             Name: Frank, Age: 32
//             Value: 7878
//          p2 instance values:
//             Name: Sam, Age: 42
//             Value: 7878
//       
//       Values of p1 and p3 after changes to p1:
//          p1 instance values:
//             Name: George, Age: 39
//             Value: 8641
//          p3 instance values:
//             Name: Frank, Age: 32
//             Value: 7878

為了實現深度復制,我們就必須遍歷有相互引用的對象構成的圖,並需要處理其中的循環引用結構。這無疑是十分復雜的。幸好借助.Net的序列化和反序列化機制,可以十分簡單的深度Clone一個對象。

原理很簡單,首先將對象序列化到內存流中,此時對象和對象引用的所用對象的狀態都被保存到內存中。.Net的序列化機制會自動處理循環引用的情況。然後將內存流中的狀態信息反序列化到一個新的對象中。

這樣一個對象的深度復制就完成了。在原型設計模式中CLONE技術非常關鍵。

using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

namespace CloneDemo
{
    [Serializable]
    class DemoClass
    {
        public int i = 0;
        public int[] iArr = { 1, 2, 3 };

        public DemoClass Clone1() //淺CLONE
        {
            return this.MemberwiseClone() as DemoClass;
        }

        public DemoClass Clone2() //深clone
        {
            MemoryStream stream = new MemoryStream();
            BinaryFormatter formatter = new BinaryFormatter();
            formatter.Serialize(stream, this);
            stream.Position = 0;
            return formatter.Deserialize(stream) as DemoClass;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            DemoClass a = new DemoClass();
            a.i = 10;
            a.iArr = new int[] { 8, 9, 10 };
            DemoClass b = a.Clone1();
            DemoClass c = a.Clone2();

            // 更改 a 對象的iArr[0], 導致 b 對象的iArr[0] 也發生了變化 而 c不會變化
              a.iArr[0] = 88;

            Console.WriteLine("MemberwiseClone");
            Console.WriteLine(b.i);
            foreach (var item in b.iArr)
            {
                Console.WriteLine(item);
            }

            Console.WriteLine("Clone2");
            Console.WriteLine(c.i);
            foreach (var item in c.iArr)
            {
                Console.WriteLine(item);
            }

            Console.ReadLine();
        }
    }
}

  引用:http://www.cnblogs.com/zhangji/archive/2011/02/23/1961897.html

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved