天天看點

設計模式-值類型與引用類型、深拷貝與淺拷貝、原型模式詳解一. 值類型和引用類型1. 前言2. 對象的傳遞3. 參數按值傳遞4. 參數按引用類型傳遞5. string和其它引用類型的差別6. 拆箱和裝箱7. 總結二. 深拷貝和淺拷貝1. 淺拷貝2. 深拷貝3. 二者差別4. .Net中實作5. 經過測試得出來一個結論三. 原型模式詳解1. 背景2. 定義和特點3. 具體實作4. 使用場景

一. 值類型和引用類型

1. 前言

(1). 分類

  值類型包括:布爾類型、浮點類型(float、double、decimal、byte)、字元類型(char)、整型(int、long、short等)、枚舉(entum)、結構體(struct)。

  引用類型:數組、字元串(string)、類、接口、委托(delegate)。

(2).記憶體存儲

  值類型資料存放在棧stack中, 引用類型位址存放棧stack中,資料存放在堆heap中。

  值類型變量聲明後,不管是否指派,都會在在棧中配置設定記憶體空間。引用類型聲明時,隻在棧中配置設定記憶體,用于存放位址,并沒有在堆上配置設定記憶體空間。

2. 對象的傳遞

(1). 将值類型的變量指派給另一個變量,會執行一次指派,指派變量包含的值。

(2). 将引用類型的變量指派給另一個引用類型變量,它複制的是引用對象的記憶體位址,在指派後就會多個變量指向同一個引用對象執行個體。

代碼分享:

Console.WriteLine("------------------------下面是值類型和引用類型指派-----------------------------");
                    //值類型指派
                    int a = 0;
                    int b = a;
                    Console.WriteLine($"預設值: a={a},b={b}");
                    a = 1;
                    Console.WriteLine($"修改a的值後: a={a},b={b}");
                    b = 2;
                    Console.WriteLine($"修改b的值後: a={a},b={b}");

                    //引用類型指派
                    Student stu1 = new Student();
                    stu1.age = 20;
                    Student stu2 = stu1;
                    Console.WriteLine($"預設值: stu1.age={ stu1.age}, stu2.age={stu2.age}");
                    stu1.age = 30;
                    Console.WriteLine($"修改stu1.age的值後:stu1.age={ stu1.age}, stu2.age={stu2.age}");
                    stu2.age = 40;
                    Console.WriteLine($"修改stu2.age的值後: stu1.age={ stu1.age}, stu2.age={stu2.age}");
           

運作結果:

設計模式-值類型與引用類型、深拷貝與淺拷貝、原型模式詳解一. 值類型和引用類型1. 前言2. 對象的傳遞3. 參數按值傳遞4. 參數按引用類型傳遞5. string和其它引用類型的差別6. 拆箱和裝箱7. 總結二. 深拷貝和淺拷貝1. 淺拷貝2. 深拷貝3. 二者差別4. .Net中實作5. 經過測試得出來一個結論三. 原型模式詳解1. 背景2. 定義和特點3. 具體實作4. 使用場景

3. 參數按值傳遞

(1). 對于值類型(age),傳遞的是該值類型執行個體的一個副本,是以原本的值age并沒有改變。

(2). 對于引用類型(Student stu),傳遞是變量stu的引用位址(即stu對象執行個體的記憶體位址)拷貝副本,是以他們操作都是同一個stu對象執行個體。

代碼分享:

{
                    Console.WriteLine("------------------------下面是參數按值傳遞-----------------------------");
                    //值類型按值傳遞
                    int age1 = 60;
                    Utils.AddAge1(age1);
                    Console.WriteLine($"age={age1}");

                    //引用類型按值傳遞
                    Student stu2 = new Student();
                    stu2.age = 100;
                    Utils.ReduceAge1(stu2);
                    Console.WriteLine($"age={stu2.age}");
}
public class Utils
{
        public static void ReduceAge1(Student stu)
        {
            stu.age -= 10;
            Console.WriteLine($"ReduceAge  age={stu.age}");
        }

        public static void AddAge1(int age)
        {
            age += 10;
            Console.WriteLine($"AddAge age ={age}");
        }

        public static void ReduceAge2(ref Student stu)
        {
            stu.age -= 10;
            Console.WriteLine($"ReduceAge  age={stu.age}");
        }

        public static void AddAge2(ref int age)
        {
            age += 10;
            Console.WriteLine($"AddAge age ={age}");
        }

}
           

運作結果:

設計模式-值類型與引用類型、深拷貝與淺拷貝、原型模式詳解一. 值類型和引用類型1. 前言2. 對象的傳遞3. 參數按值傳遞4. 參數按引用類型傳遞5. string和其它引用類型的差別6. 拆箱和裝箱7. 總結二. 深拷貝和淺拷貝1. 淺拷貝2. 深拷貝3. 二者差別4. .Net中實作5. 經過測試得出來一個結論三. 原型模式詳解1. 背景2. 定義和特點3. 具體實作4. 使用場景

4. 參數按引用類型傳遞

 不管是值類型還是引用類型,可以使用ref或out關鍵字來實作參數的按引用傳遞。ref或out關鍵字告訴編譯器,方法傳遞的是參數位址,而非參數本身。在按引用傳遞時,方法的定義和調用都必須顯式的使用ref或out關鍵字,不可以省略,否則會引起編譯錯誤。

代碼分享:

{
                    Console.WriteLine("------------------------下面是參數按引用傳遞-----------------------------");
                    //值類型按值傳遞
                    int age1 = 60;
                    Utils.AddAge2(ref age1);
                    Console.WriteLine($"age={age1}");

                    //引用類型按值傳遞
                    Student stu2 = new Student();
                    stu2.age = 100;
                    Utils.ReduceAge2(ref stu2);
                    Console.WriteLine($"age={stu2.age}");
}
 public class Utils
    {
        public static void ReduceAge1(Student stu)
        {
            stu.age -= 10;
            Console.WriteLine($"ReduceAge  age={stu.age}");
        }

        public static void AddAge1(int age)
        {
            age += 10;
            Console.WriteLine($"AddAge age ={age}");
        }

        public static void ReduceAge2(ref Student stu)
        {
            stu.age -= 10;
            Console.WriteLine($"ReduceAge  age={stu.age}");
        }

        public static void AddAge2(ref int age)
        {
            age += 10;
            Console.WriteLine($"AddAge age ={age}");
        }
    }
           

運作結果:

設計模式-值類型與引用類型、深拷貝與淺拷貝、原型模式詳解一. 值類型和引用類型1. 前言2. 對象的傳遞3. 參數按值傳遞4. 參數按引用類型傳遞5. string和其它引用類型的差別6. 拆箱和裝箱7. 總結二. 深拷貝和淺拷貝1. 淺拷貝2. 深拷貝3. 二者差別4. .Net中實作5. 經過測試得出來一個結論三. 原型模式詳解1. 背景2. 定義和特點3. 具體實作4. 使用場景

更多C++背景開發技術點知識内容包括C/C++,Linux,Nginx,ZeroMQ,MySQL,Redis,MongoDB,ZK,流媒體,音視訊開發,Linux核心,TCP/IP,協程,DPDK多個進階知識點。

C/C++Linux伺服器開發進階架構師/C++背景開發架構師免費學習位址

【文章福利】另外還整理一些C++背景開發架構師 相關學習資料,面試題,教學視訊,以及學習路線圖,免費分享有需要的可以點選領取

設計模式-值類型與引用類型、深拷貝與淺拷貝、原型模式詳解一. 值類型和引用類型1. 前言2. 對象的傳遞3. 參數按值傳遞4. 參數按引用類型傳遞5. string和其它引用類型的差別6. 拆箱和裝箱7. 總結二. 深拷貝和淺拷貝1. 淺拷貝2. 深拷貝3. 二者差別4. .Net中實作5. 經過測試得出來一個結論三. 原型模式詳解1. 背景2. 定義和特點3. 具體實作4. 使用場景

5. string和其它引用類型的差別

(1). 在string字元串,一開始s1位址指向是ypf,因為s2=s1,是以s2位址也同樣指向ypf;當s1再次指派lmr時,堆中就會開辟出資料lmr,而且ypf沒有消失,沒有被覆寫。s1位址就指向lmr,s2位址還是原來的ypf。

(2). 在引用類型數組上,一開始arry1和arry2的位址都指向{1,2,3},當給arry1進行資料更改時,由于是引用類型,是以在{1,2,3}上面進行更改,就會對arry2進行覆寫。

代碼如下:

{
                    Console.WriteLine("------------------------下面是string和其它引用類型的差別-----------------------------");
                    //string類型的測試
                    string s1 = "ypf";
                    string s2 = s1;
                    Console.WriteLine($"s1={s1},s2={s2}");
                    //修改s1的值
                    s1 = "lmr";
                    Console.WriteLine($"s1={s1},s2={s2}");

                    //其它引用類型的測試
                    int[] arry1 = new int[] { 1, 2, 3 };
                    int[] arry2 = arry1;
                    Console.WriteLine($"預設值:arry1[0]={arry1[0]},arry1[1]={arry1[1]},arry1[2]={arry1[2]}");
                    Console.WriteLine($"預設值:arry2[0]={arry2[0]},arry2[1]={arry2[1]},arry2[2]={arry2[2]}");

                    arry1[2] = 0;
                    Console.WriteLine($"修改後:arry1[0]={arry1[0]},arry1[1]={arry1[1]},arry1[2]={arry1[2]}");
                    Console.WriteLine($"修改後:arry2[0]={arry2[0]},arry2[1]={arry2[1]},arry2[2]={arry2[2]}");

 }
           

運作效果:

設計模式-值類型與引用類型、深拷貝與淺拷貝、原型模式詳解一. 值類型和引用類型1. 前言2. 對象的傳遞3. 參數按值傳遞4. 參數按引用類型傳遞5. string和其它引用類型的差別6. 拆箱和裝箱7. 總結二. 深拷貝和淺拷貝1. 淺拷貝2. 深拷貝3. 二者差別4. .Net中實作5. 經過測試得出來一個結論三. 原型模式詳解1. 背景2. 定義和特點3. 具體實作4. 使用場景

string變化圖如下:

設計模式-值類型與引用類型、深拷貝與淺拷貝、原型模式詳解一. 值類型和引用類型1. 前言2. 對象的傳遞3. 參數按值傳遞4. 參數按引用類型傳遞5. string和其它引用類型的差別6. 拆箱和裝箱7. 總結二. 深拷貝和淺拷貝1. 淺拷貝2. 深拷貝3. 二者差別4. .Net中實作5. 經過測試得出來一個結論三. 原型模式詳解1. 背景2. 定義和特點3. 具體實作4. 使用場景
設計模式-值類型與引用類型、深拷貝與淺拷貝、原型模式詳解一. 值類型和引用類型1. 前言2. 對象的傳遞3. 參數按值傳遞4. 參數按引用類型傳遞5. string和其它引用類型的差別6. 拆箱和裝箱7. 總結二. 深拷貝和淺拷貝1. 淺拷貝2. 深拷貝3. 二者差別4. .Net中實作5. 經過測試得出來一個結論三. 原型模式詳解1. 背景2. 定義和特點3. 具體實作4. 使用場景

Array類型變化圖如下:

設計模式-值類型與引用類型、深拷貝與淺拷貝、原型模式詳解一. 值類型和引用類型1. 前言2. 對象的傳遞3. 參數按值傳遞4. 參數按引用類型傳遞5. string和其它引用類型的差別6. 拆箱和裝箱7. 總結二. 深拷貝和淺拷貝1. 淺拷貝2. 深拷貝3. 二者差別4. .Net中實作5. 經過測試得出來一個結論三. 原型模式詳解1. 背景2. 定義和特點3. 具體實作4. 使用場景
設計模式-值類型與引用類型、深拷貝與淺拷貝、原型模式詳解一. 值類型和引用類型1. 前言2. 對象的傳遞3. 參數按值傳遞4. 參數按引用類型傳遞5. string和其它引用類型的差別6. 拆箱和裝箱7. 總結二. 深拷貝和淺拷貝1. 淺拷貝2. 深拷貝3. 二者差別4. .Net中實作5. 經過測試得出來一個結論三. 原型模式詳解1. 背景2. 定義和特點3. 具體實作4. 使用場景

6. 拆箱和裝箱

 裝箱是值類型向引用類型轉換時發生的,拆箱是引用類型向值類型轉換時發生的。裝箱是隐式的,拆箱是顯式的

代碼分享:

{
                    Console.WriteLine("------------------------下面是拆箱和裝箱-----------------------------");
                    int a = 123;
                    object obj = a;  //裝箱(隐式)
                    Console.WriteLine($"裝箱後的結果obj={obj}");

                    int b = (int)obj; //拆箱(顯式)
                    Console.WriteLine($"拆箱後的結果b={b}");
}
           

運作效果

設計模式-值類型與引用類型、深拷貝與淺拷貝、原型模式詳解一. 值類型和引用類型1. 前言2. 對象的傳遞3. 參數按值傳遞4. 參數按引用類型傳遞5. string和其它引用類型的差別6. 拆箱和裝箱7. 總結二. 深拷貝和淺拷貝1. 淺拷貝2. 深拷貝3. 二者差別4. .Net中實作5. 經過測試得出來一個結論三. 原型模式詳解1. 背景2. 定義和特點3. 具體實作4. 使用場景

7. 總結

(1). 值類型有更好的效率,但不支援多态,适合用作存儲資料的載體。而引用類型支援多态,适合用于定義程式的行為。

(2). 引用類型可以派生新的類型,而值類型不能。

二. 深拷貝和淺拷貝

1. 淺拷貝

 建立一個新對象,這個對象有着原始對象屬性值的一份精确拷貝。如果屬性是值類型和string類型,拷貝的就是基本類型的值;如果屬性是引用類型,拷貝的就是記憶體位址(string類型除外),是以修改其中一個對象,就會影響到另一個對象。

2. 深拷貝

 将一個對象從記憶體中完整的拷貝一份出來,從堆記憶體中開辟一個新的區域存放新對象,且修改新對象和原對象的修改不會互相影響.

3. 二者差別

 最根本的差別在于是否真正擷取一個對象的複制實體,而不是引用,假設B複制了A,修改A的時候,看B是否發生變化:

(1).如果B跟着也變了,說明是淺拷貝,拿人手短!(修改堆記憶體中的同一個值)

(2).如果B沒有改變,說明是深拷貝,自食其力!(修改堆記憶體中的不同的值)

簡單的來說:

 如果拷貝的時候共享被引用的對象就是淺拷貝,如果被引用的對象也拷貝一份出來就是深拷貝。(深拷貝就是說重新new一個對象,然後把之前的那個對象的屬性值在重新指派給這個使用者)

4. .Net中實作

(1).淺拷貝通過MemberwiseClone()方法實作.

(2).深拷貝可以通過流的方式和反射的方式來實作,其中流的方式類前必須加 [Serializable], 反射的方式需要考慮的問題很多,嵌套以及各種類型, 此處提供的方法并不完善.

代碼分享:

/// <summary>
        /// 克隆方法(基于淺拷貝)
        /// 用于實作ICloneable裡方法(當然你用來實作深拷貝也可以)
        /// </summary>
        /// <returns></returns>
        public object Clone()
        {
            return this.MemberwiseClone();
        }


        /// <summary>
        /// 克隆方法(基于深拷貝)
        /// 類前面必須加可序列化标志[Serializable]
        /// </summary>
        /// <returns></returns>
        public object DeepClone1()
        {
            using (MemoryStream stream = new MemoryStream())
            {
                BinaryFormatter bFormatter = new BinaryFormatter();
                bFormatter.Serialize(stream, this);
                stream.Seek(0, SeekOrigin.Begin);
                return bFormatter.Deserialize(stream);
            }
        }
           

基于反射的深拷貝:(僅供參考,不是很完善)

public class Utils
    {    
        /// <summary>
        /// 基于反射的深拷貝
        /// (存在問題,不是很好用)
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static object DeepClone(Object obj)
        {
            Type type = obj.GetType();
            //對于沒有公共無參構造函數的類型此處會報錯
            object returnObj = Activator.CreateInstance(type);
            FieldInfo[] fields = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
            for (int i = 0; i < fields.Length; i++)
            {
                FieldInfo field = fields[i];
                var fieldValue = field.GetValue(obj);
                ///值類型,字元串,枚舉類型直接把值複制,不存在淺拷貝
                if (fieldValue.GetType().IsValueType || fieldValue.GetType().Equals(typeof(System.String)) || fieldValue.GetType().IsEnum)
                {
                    field.SetValue(returnObj, fieldValue);
                }
                else
                {
                    field.SetValue(returnObj, DeepClone(fieldValue));
                }
            }
            //屬性
            PropertyInfo[] properties = type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
            for (int i = 0; i < properties.Length; i++)
            {
                PropertyInfo property = properties[i];
                var propertyValue = property.GetValue(obj);
                if (propertyValue.GetType().IsValueType || propertyValue.GetType().Equals(typeof(System.String)) || propertyValue.GetType().IsEnum)
                {
                    property.SetValue(returnObj, propertyValue);
                }
                else
                {
                    property.SetValue(returnObj, DeepClone(propertyValue));
                }
            }

            return returnObj;
        }
  
    }
           

5. 經過測試得出來一個結論

(1).對于淺拷貝:所有值類型和string這個引用類型修改其中一個對象的值,不互相影響; 除了string以外的引用類型都互相影響; 類屬于引用類型,修改類中的一個屬性值,被拷貝的另一個對象的屬性值也會發生變化(與類中的屬性值是什麼類型沒有關系).

(2).對于深拷貝:無論是值類型還是引用類型, 修改其中一個對象的值都不會互相影響。

代碼分享:

/// <summary>
    /// Video視訊類
    /// </summary>
    [Serializable]
    public class Video : ICloneable
    {
        public string Id { set; get; } // 視訊編号
        public string Content { set; get; } // 視訊内容

        public List<int> ageList { set; get; }

        public VideoDetails vDetails { get; set; }

        /// <summary>
        /// 克隆方法(基于淺拷貝)
        /// 用于實作ICloneable裡方法(當然你用來實作深拷貝也可以)
        /// </summary>
        /// <returns></returns>
        public object Clone()
        {
            return this.MemberwiseClone();
        }

        /// <summary>
        /// 克隆方法(基于深拷貝)
        /// 類前面必須加可序列化标志[Serializable]
        /// </summary>
        /// <returns></returns>
        public object DeepClone1()
        {
            using (MemoryStream stream = new MemoryStream())
            {
                BinaryFormatter bFormatter = new BinaryFormatter();
                bFormatter.Serialize(stream, this);
                stream.Seek(0, SeekOrigin.Begin);
                return bFormatter.Deserialize(stream);
            }
        }
    }
    /// <summary>
    /// 視訊詳情類
    /// </summary>
    [Serializable]
    public class VideoDetails
    {
        public string videoUrl { get; set; }

        public int videoPic { get; set; }

        public VideoDetails(string myVideoUrl, int myVideoPic)
        {
            this.videoUrl = myVideoUrl;
            this.videoPic = myVideoPic;
        }
    }
           

測試代碼

#region 淺拷貝
                {
                    Console.WriteLine("-------------------------------下面是基于淺拷貝------------------------------------");
                    Video v1 = new Video()
                    {
                        Id = "001",
                        Content = "西遊記",
                        ageList = new List<int>() { 000 },  //List是引用類型
                        vDetails = new VideoDetails(@"H:\DesignMode", 1111) //類也是引用類型
                    };

                    Video v2 = (Video)v1.Clone();
                    Console.WriteLine($"v2: Id={v2.Id},Content={v2.Content},ageList[0]={ v1.ageList[0]},Url={v2.vDetails.videoUrl},videoPic={v2.vDetails.videoPic}");
                    //修改v1的值,v2中的屬性是否變化要分情況讨論的
                    v1.Content = "水浒傳";
                    v1.ageList[0] = 111;
                    v1.vDetails.videoUrl = @"H:\XXXXXXX";
                    v1.vDetails.videoPic = 22222;
                    Console.WriteLine($"v2: Id={v2.Id},Content={v2.Content},ageList[0]={ v2.ageList[0]},Url={v2.vDetails.videoUrl},videoPic={v2.vDetails.videoPic}");
                }
                #endregion

                #region 深拷貝1(流的模式)
                {
                    Console.WriteLine("-------------------------------下面是基于深拷貝1------------------------------------");
                    Video v1 = new Video()
                    {
                        Id = "001",
                        Content = "西遊記",
                        ageList = new List<int>() { 000 },
                        vDetails = new VideoDetails(@"H:\DesignMode", 1111)
                    };

                    Video v2 = (Video)v1.DeepClone1();
                    Console.WriteLine($"v2: Id={v2.Id},Content={v2.Content},ageList[0]={ v1.ageList[0]},Url={v2.vDetails.videoUrl},videoPic={v2.vDetails.videoPic}");
                    //修改v1的值,v2不變
                    v1.Content = "水浒傳";
                    v1.vDetails.videoUrl = @"H:\XXXXXXX";
                    v1.vDetails.videoPic = 22222;
                    Console.WriteLine($"v2: Id={v2.Id},Content={v2.Content},ageList[0]={ v2.ageList[0]},Url={v2.vDetails.videoUrl},videoPic={v2.vDetails.videoPic}");
                }
                #endregion
           

運作結果:

設計模式-值類型與引用類型、深拷貝與淺拷貝、原型模式詳解一. 值類型和引用類型1. 前言2. 對象的傳遞3. 參數按值傳遞4. 參數按引用類型傳遞5. string和其它引用類型的差別6. 拆箱和裝箱7. 總結二. 深拷貝和淺拷貝1. 淺拷貝2. 深拷貝3. 二者差別4. .Net中實作5. 經過測試得出來一個結論三. 原型模式詳解1. 背景2. 定義和特點3. 具體實作4. 使用場景

三. 原型模式詳解

1. 背景

 在有些系統中,存在大量相同或相似對象的建立問題,如果用傳統的構造函數來建立對象,會比較複雜且耗時耗資源,用原型模式生成對象就很高效,就像孫悟空拔下猴毛輕輕一吹就變出很多孫悟空一樣簡單。

2. 定義和特點

 定義如下:用一個已經建立的執行個體作為原型,通過複制該原型對象來建立一個和原型相同或相似的新對象。在這裡,原型執行個體指定了要建立的對象的種類。用這種方式建立對象非常高效,根本無須知道對象建立的細節。例如,Windows 作業系統的安裝通常較耗時,如果複制就快了很多。

3. 具體實作

(1). 模式結構

 A. 抽象原型類:規定了具體原型對象必須實作的接口,eg:.Net 中的ICloneable。

 B. 具體原型類:實作抽象原型類的 clone() 方法,它是可被複制的對象。

 C. 通路類:使用具體原型類中的 clone() 方法來複制新的對象。

結構圖如下:

設計模式-值類型與引用類型、深拷貝與淺拷貝、原型模式詳解一. 值類型和引用類型1. 前言2. 對象的傳遞3. 參數按值傳遞4. 參數按引用類型傳遞5. string和其它引用類型的差別6. 拆箱和裝箱7. 總結二. 深拷貝和淺拷貝1. 淺拷貝2. 深拷貝3. 二者差別4. .Net中實作5. 經過測試得出來一個結論三. 原型模式詳解1. 背景2. 定義和特點3. 具體實作4. 使用場景

(2). 使用場景

 有一塊視訊,我需要1個一模一樣的,并且我還需要1個除了路徑不同其它都相同的視訊,這個時候可以使用原型模式哦。

(3). 代碼實操

相關類:

/// <summary>
    /// Video視訊類
    /// </summary>
    [Serializable]
    public class Video : ICloneable
    {
        public string Id { set; get; } // 視訊編号
        public string Content { set; get; } // 視訊内容

        public List<int> ageList { set; get; }

        public VideoDetails vDetails { get; set; }

        /// <summary>
        /// 克隆方法(基于淺拷貝)
        /// 用于實作ICloneable裡方法(當然你用來實作深拷貝也可以)
        /// </summary>
        /// <returns></returns>
        public object Clone()
        {
            return this.MemberwiseClone();
        }

        /// <summary>
        /// 克隆方法(基于深拷貝)
        /// 類前面必須加可序列化标志[Serializable]
        /// </summary>
        /// <returns></returns>
        public object DeepClone1()
        {
            using (MemoryStream stream = new MemoryStream())
            {
                BinaryFormatter bFormatter = new BinaryFormatter();
                bFormatter.Serialize(stream, this);
                stream.Seek(0, SeekOrigin.Begin);
                return bFormatter.Deserialize(stream);
            }
        }
    }

    /// <summary>
    /// 視訊詳情類
    /// </summary>
    [Serializable]
    public class VideoDetails
    {
        public string videoUrl { get; set; }

        public int videoPic { get; set; }

        public VideoDetails(string myVideoUrl, int myVideoPic)
        {
            this.videoUrl = myVideoUrl;
            this.videoPic = myVideoPic;
        }
    }
           

測試代碼:

#region 01-完全相同視訊的拷貝
                {
                    Console.WriteLine("------------------------------- 01-完全相同視訊的拷貝------------------------------------");
                    Video v1 = new Video()
                    {
                        Id = "001",
                        Content = "西遊記",
                        ageList = new List<int>() { 000 },
                        vDetails = new VideoDetails(@"H:\DesignMode", 1111)
                    };
                    Video v2 = (Video)v1.DeepClone1();  //深拷貝
                    Console.WriteLine($"v1: Id={v1.Id},Content={v1.Content},ageList[0]={ v1.ageList[0]},Url={v1.vDetails.videoUrl},videoPic={v1.vDetails.videoPic}");

                    Console.WriteLine($"v2: Id={v2.Id},Content={v2.Content},ageList[0]={ v2.ageList[0]},Url={v2.vDetails.videoUrl},videoPic={v2.vDetails.videoPic}");
                }
                #endregion


                #region 02-相似視訊的拷貝
                {
                    Console.WriteLine("-------------------------------02-相似視訊的拷貝------------------------------------");
                    Video v1 = new Video()
                    {
                        Id = "001",
                        Content = "西遊記",
                        ageList = new List<int>() { 000 },
                        vDetails = new VideoDetails(@"H:\DesignMode", 1111)
                    };

                    Video v2 = (Video)v1.DeepClone1();  //深拷貝
                    Console.WriteLine($"v1: Id={v1.Id},Content={v1.Content},ageList[0]={ v1.ageList[0]},Url={v1.vDetails.videoUrl},videoPic={v1.vDetails.videoPic}");
                    //相似視訊的拷貝,隻需要簡單修改即可
                    v2.vDetails.videoUrl = @"F:\newVideo";
                    Console.WriteLine($"v2: Id={v2.Id},Content={v2.Content},ageList[0]={ v2.ageList[0]},Url={v2.vDetails.videoUrl},videoPic={v2.vDetails.videoPic}");
                }
                #endregion
           

運作結果:

設計模式-值類型與引用類型、深拷貝與淺拷貝、原型模式詳解一. 值類型和引用類型1. 前言2. 對象的傳遞3. 參數按值傳遞4. 參數按引用類型傳遞5. string和其它引用類型的差別6. 拆箱和裝箱7. 總結二. 深拷貝和淺拷貝1. 淺拷貝2. 深拷貝3. 二者差別4. .Net中實作5. 經過測試得出來一個結論三. 原型模式詳解1. 背景2. 定義和特點3. 具體實作4. 使用場景

4. 使用場景

(1). 對象之間相同或相似,即隻是個别的幾個屬性不同的時候。

(2). 對象的建立過程比較麻煩,但複制比較簡單的時候。

原文連結:第三節: 值類型與引用類型、深拷貝與淺拷貝、原型模式詳解 - Yaopengfei - 部落格園

繼續閱讀