C# 淺拷貝與深拷貝區別 解惑篇

來源:互聯網
上載者:User

問題起源:

昨天被同事問到一個淺拷貝與深拷貝區別的問題,說實在的,記得在學校時在書在看過相關概念區別。
只是,那時的在校生,又有幾個能對書本上那寫的盡量讓鬼都看不懂知識能清晰的理解呢。
工作後雖然也有用到Clone相關的內容,不過也僅是應用,基礎的概念還是沒去仔細的理解,以於後來DataTable內部那不深不淺的架構拷貝都混和這些概念混在一起了。

曾經的以為:

讓得一年多以前,我去面試,被一個人問到淺拷貝與深拷貝區別,我答:淺拷貝就是拷貝就是拷貝架構,不包括值,深拷貝就是連值也一同拷貝。
當我答出這樣錯誤的答案時,對方沒有糾正,反而似乎對我的答案還挺滿意的。
唉,面試管自己不懂還問我這問題,還讓我一直以為到現在都是這個樣。

同事的質問:

接著同事說它的樣本裡,發現值是有拷貝的,於是我意識到我的認知是有問題了,我重新百度了一下。
網上亂七雜八的答案,讓我得一個模糊的似乎正確的答案:淺拷貝不拷貝內部類的對象

引申出的錯亂:

接著同事的疑問更一度把我引向這個容易迷亂的錯誤深淵:淺拷貝是對參考型別拷貝地址,對實值型別直接進行拷貝。

 

最後,為瞭解惑,還是用樣本來說話了:

    class DemoClass : ICloneable
    {
        public int intValue = 1;
        public string strValue = "1";
        public PersonEnum pEnum = PersonEnum.EnumA;
        public PersonStruct pStruct = new PersonStruct();
        public Person pClass = new Person("1");        public int[] pIntArray = new int[] { 1 };
        public string[] pArray = new string[] { "1" };
        #region ICloneable 成員

         public DemoClass()
        {
            pStruct.StructValue = 1;
        }
        public object Clone()
        {
           return this.MemberwiseClone();
        }
        #endregion
    }

    class Person
    {
        public string Name;

        public Person(string name)
        {
            Name = name;
        }

    }
    public enum PersonEnum
    {
        EnumA=1,
        EnumB=2
    }
    public struct PersonStruct
    {
      public  int StructValue;
    }

說明:

這裡的樣本,我用上了:
int
stringint[]
string[]
enum
struct
class
然後接下來會產生執行個體A和複製執行個體B。
接著改變B的值,看A的值會不會被改變。

 

接下我們看main方法

        static void Main(string[] args)
        {
            Demo();
        }
        public static void Demo()
        {
            DemoClass A = new DemoClass();
            DemoClass B = (DemoClass)A.Clone();
            B.intValue = 2;
            Write(string.Format("        int->[A:{0}] [B:{1}]", A.intValue, B.intValue));
            B.strValue = "2";
            Write(string.Format("     string->[A:{0}] [B:{1}]", A.strValue, B.strValue));
            B.pEnum = PersonEnum.EnumB;
            Write(string.Format("       Enum->[A:{0}] [B:{1}]", (int)A.pEnum, (int)B.pEnum));
            B.pStruct.StructValue = 2;
            Write(string.Format("     struct->[A:{0}] [B:{1}]", A.pStruct.StructValue, B.pStruct.StructValue));
            B.pIntArray[0] = 2;
            Write(string.Format("   intArray->[A:{0}] [B:{1}]", A.pIntArray[0], B.pIntArray[0]));
            B.pStringArray[0] = "2";
            Write(string.Format("stringArray->[A:{0}] [B:{1}]", A.pStringArray[0], B.pStringArray[0]));
            B.pClass.Name = "2";
            Write(string.Format("      Class->[A:{0}] [B:{1}]", A.pClass.Name, B.pClass.Name));
            System.Console.Read();
        }
        static void Write(string msg)
        {
            System.Console.WriteLine(msg);
        }

說明:

我們通過改變B執行個體的值,然後列印出A和B的值看結果。

 

列印結果如下:

從最後輸出的結果我們得知:

對於內部的Class的對象和數組,會Copy地址一份。[從而改變B時,A也被改變了] 而對於其它內建的int/string/Enum/struct/object類型,則進行值copy。

 

最後,我試著百度尋找淺拷貝最原生的定義,淺搜了一下找不到,那這個定義,就留給讀者解答一下了。

 

接著,我順手比較了一下淺拷貝和深拷貝的效能測試:

先在DemoClass加入一個函數:

public object CloneNew()
{
   return new DemoClass();
}

 

接著我們寫範例程式碼比較:

        public static void Compare()
        {
            DemoClass baseClass = new DemoClass();

            DateTime start = DateTime.Now;
            for (int i = 0; i < 1000000; i++)
            {
                DemoClass newClass = (DemoClass)baseClass.Clone();
            }
            TimeSpan ts = DateTime.Now - start;
            System.Console.WriteLine("淺拷貝:" + ts.Ticks);

            DateTime start2 = DateTime.Now;
            for (int j = 0; j < 1000000; j++)
            {
                DemoClass newClass = (DemoClass)baseClass.CloneNew();
            }
            TimeSpan ts2 = DateTime.Now - start2;
            System.Console.WriteLine("深拷貝:" + ts2.Ticks);

           
            System.Console.Read();
        }

 

最後得出結果:

看來直接用淺拷貝效能還不如直接返回一個new的對象。同樣的,用複製返回object最後還得對類型轉換進行一些開銷,教人情何以堪!

 

附言:

這兩天剛好感冒,插了這兩篇解惑篇,都是臨時插進來的的問題了,接下來會繼續寫 CYQ.Data 輕量資料層之路 架構 的相關文章。

 

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.