2017年9月24日 星期日

C# : 使用 ICloneable 介面,複製一個物件

除了可以使用建構函式來進行複製一個物件,現在,讓我們來使用 C# 提供的一個介面設計模式,ICloneable,只要在類別中實作出這個介面,你設計的類別就會具有複製一個物件的能力。

了解更多關於 [ICloneable Interface
了解更多關於 [C# 程式設計手冊 



我們使用前面的建構函式的類別範例程式碼,Person,接著,在這個類別中,實作 ICloneable 介面;這個介面相當的簡單,你只需要實作出 Clone 這個方法即可。
在這裡,我們使用 System.Object 型別中的 MemberwiseClone 方法來做到物件複製的效果,MemberwiseClone 方法提供了物件淺層複製的能力,因此,在執行這個方法之後,就會建立新的物件,並再將目前物件的非靜態欄位複製到新的物件建立淺層複本,這裡產生的新物件則會在堆積記憶體上產生另外一個新的物件記憶體空間。
    class Person : ICloneable
    {
        public int Age { get; set; }
        public string Name { get; set; }

        // 宣告一個建構函式,並且進行物件成員值的初始化
        public Person(string name, int age)
        {
            Name = name;
            Age = age;
        }

        // 覆蓋 object.ToString 方法,顯示該物件的詳細資料
        public override string ToString()
        {
            return Name + " is " + Age.ToString();
        }

        public object Clone()
        {
            return this.MemberwiseClone();
        }
    }

進行測試

在底下的程式碼中,我們首先建立一個物件,person1,並且設定這個物件的 Name / Age 這兩個屬性值。
接著,我們使用複製物件的 Clone() 函式,我們就得到一個內容完全相同的物件,並且 person1 與 person2 分別指向到不同的堆積記憶體空間內。


然後,為了要確認 person1 與 person2 分別指向不同的記憶體空間,我們使用將 person1 / person2 的屬性值進行修改,並且將這兩個物件的屬性值顯示出來,就可以確認這兩個物件是在不同的堆積記憶體空間中。
    class Program
    {
        static void Main(string[] args)
        {
            // 建立一個 Person 物件,且於建構函式引數內,指定要初始化的成員值
            Person person1 = new Person("George", 40);

            // 使用複製建構函式,產生一個成員值完全相同的 Person 物件
            Person person2 = person1.Clone() as Person;

            Console.WriteLine("person1 / person2 兩個物件成員值");
            Console.WriteLine($"person1 : {person1.ToString()}");
            Console.WriteLine($"person2 : {person2.ToString()}");
            Console.WriteLine("Press any key for continuing...");
            Console.ReadKey();

            Console.WriteLine("進行修改 person1 / person2 兩個物件成員值");
            person1.Age = 39;
            person2.Age = 41;
            person2.Name = "Charles";

            Console.WriteLine("person1 / person2 兩個物件成員值");
            Console.WriteLine($"person1 : {person1.ToString()}");
            Console.WriteLine($"person2 : {person2.ToString()}");
            Console.WriteLine("Press any key for continuing...");
            Console.ReadKey();
        }
    }

了解更多關於 [ICloneable Interface
了解更多關於 [C# 程式設計手冊 





2 則留言: