欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C#淺拷貝和深拷貝實(shí)例解析

 更新時(shí)間:2014年08月13日 10:52:43   投稿:shichen2014  
這篇文章主要介紹了C#淺拷貝和深拷貝,是比較重要的概念,需要的朋友可以參考下

在有些時(shí)候,我們需要從數(shù)據(jù)庫(kù)讀取數(shù)據(jù)填充對(duì)象或從硬盤(pán)讀取文件填充對(duì)象,但是這樣做相對(duì)耗時(shí)。這時(shí)候我們就想到了對(duì)象的拷貝。本文即以實(shí)例形式解析了C#淺拷貝和深拷貝的用法。具體如下:

一、淺拷貝

1.什么是"淺拷貝":

當(dāng)針對(duì)一個(gè)對(duì)象前拷貝的時(shí)候,對(duì)于對(duì)象的值類(lèi)型成員,會(huì)復(fù)制其本身,對(duì)于對(duì)象的引用類(lèi)型成員,僅僅復(fù)制對(duì)象引用,這個(gè)引用指向托管堆上的對(duì)象實(shí)例。

2.有一個(gè)對(duì)象,包含引用類(lèi)型的類(lèi)成員和值類(lèi)型的struct成員

Cinema包含引用類(lèi)型成員Room和值類(lèi)型成員Film。

  public class Room
  {
    public int _maxSeat;
 
    public Room(int maxSeat)
    {
      this._maxSeat = maxSeat;
    }
  }
 
  public struct Film
  {
    public string _name;
 
    public Film(string name)
    {
      this._name = name;
    }
  }
 
  public class Cinema
  {
    public Room _room;
    public Film _film;
 
    public Cinema(Room room, Film film)
    {
      this._room = room;
      this._film = film;
    }
 
    public object Clone()
    {
      return MemberwiseClone(); //對(duì)引用類(lèi)型實(shí)施淺復(fù)制
    }
  }
 

3.測(cè)試拷貝后的效果

①打印出原先對(duì)象拷貝前值類(lèi)型和引用類(lèi)型成員的值
②對(duì)原先對(duì)象拷貝,打印出復(fù)制對(duì)象值類(lèi)型和引用類(lèi)型成員的值
③改變?cè)葘?duì)象的值,再次打印原先對(duì)象的值類(lèi)型和引用類(lèi)型成員的值
④再次打印復(fù)制對(duì)象值類(lèi)型和引用類(lèi)型成員的值

static void Main(string[] args)
{
  Room room1 = new Room(60);
  Film film1 = new Film("家園防線");
  Cinema cinema1 = new Cinema(room1, film1);
  Cinema cinema2 = (Cinema)cinema1.Clone();
  Console.WriteLine("拷貝之前,結(jié)構(gòu)成員的字段值為{0},引用類(lèi)型成員的字段值為{1}", cinema1._film._name,cinema1._room._maxSeat);

  Console.WriteLine("拷貝之后,新的結(jié)構(gòu)成員的字段值為{0},引用類(lèi)型成員的字段值為{1}", cinema2._film._name, cinema2._room._maxSeat);

  //修改拷貝之前引用類(lèi)型的字段值
  cinema1._film._name = "極品飛車(chē)";
  cinema1._room._maxSeat = 80;

  Console.WriteLine("修改之后,結(jié)構(gòu)成員的字段值為{0},引用類(lèi)型成員的字段值為{1}", cinema1._film._name, cinema1._room._maxSeat);
  Console.WriteLine("修改之后,新的結(jié)構(gòu)成員的字段值為{0},引用類(lèi)型成員的字段值為{1}", cinema2._film._name, cinema2._room._maxSeat);

  Console.ReadKey();
}

運(yùn)行結(jié)果如下:

分析:

淺拷貝關(guān)鍵點(diǎn)是對(duì)引用類(lèi)型拷貝的是對(duì)象引用,這個(gè)引用指向托管堆上的對(duì)象實(shí)例。改變?cè)瓕?duì)應(yīng)引用類(lèi)型的值,會(huì)影響到復(fù)制對(duì)象。

二、深拷貝

1.什么是"深拷貝"

對(duì)引用成員指向的對(duì)象也進(jìn)行復(fù)制,在托管堆上賦值原先對(duì)象實(shí)例所包含的數(shù)據(jù),再在托管堆上創(chuàng)建新的對(duì)象實(shí)例。

2.通過(guò)對(duì)每個(gè)對(duì)象成員進(jìn)行復(fù)制進(jìn)行深拷貝

    public object Clone()
    {
      Room room = new Room();
      room._maxSeat = this._room._maxSeat;//復(fù)制當(dāng)前引用類(lèi)型成員的值到新對(duì)象 
      Film film = this._film; //值類(lèi)型直接賦值
      Cinema cinema = new Cinema(room, film);
      return cinema;
    }
 

3.也可以通過(guò)序列化和反序列化進(jìn)行深拷貝

    public object Clone1()
    {
      BinaryFormatter bf = new BinaryFormatter();
      MemoryStream ms = new MemoryStream();
      bf.Serialize(ms, this); //復(fù)制到流中
      ms.Position = 0;
      return (bf.Deserialize(ms));
    }

4.采用序列化和反序列化深拷貝,但必須把所有的類(lèi)打上[Serializable],測(cè)試代碼如下:

  [Serializable]
  public class Room
  {
    public int _maxSeat;
 
    public Room()
    {}
 
    public Room(int maxSeat)
    {
      this._maxSeat = maxSeat;
    }
  }
 
  [Serializable]
  public struct Film
  {
    public string _name;
 
    public Film(string name)
    {
      this._name = name;
    }
  }
 
  [Serializable]
  public class Cinema
  {
    public Room _room;
    public Film _film;
 
    public Cinema(Room room, Film film)
    {
      this._room = room;
      this._film = film;
    }
 
    //淺拷貝
    //public object Clone()
    //{
    //  return MemberwiseClone(); //對(duì)引用類(lèi)型實(shí)施淺復(fù)制
    //}
 
    //深拷貝 對(duì)每個(gè)對(duì)象成員進(jìn)行復(fù)制
    public object Clone()
    {
      Room room = new Room();
      room._maxSeat = this._room._maxSeat;//復(fù)制當(dāng)前引用類(lèi)型成員的值到新對(duì)象 
      Film film = this._film; //值類(lèi)型直接賦值
      Cinema cinema = new Cinema(room, film);
      return cinema;
    }
 
    //使用序列化和反序列化進(jìn)行復(fù)制
    public object Clone1()
    {
      BinaryFormatter bf = new BinaryFormatter();
      MemoryStream ms = new MemoryStream();
      bf.Serialize(ms, this); //復(fù)制到流中
      ms.Position = 0;
      return (bf.Deserialize(ms));
    }
  }

5.測(cè)試拷貝后的效果

①打印出原先對(duì)象拷貝前值類(lèi)型和引用類(lèi)型成員的值
②對(duì)原先對(duì)象拷貝,打印出復(fù)制對(duì)象值類(lèi)型和引用類(lèi)型成員的值
③改變?cè)葘?duì)象的值,再次打印原先對(duì)象的值類(lèi)型和引用類(lèi)型成員的值
④再次打印復(fù)制對(duì)象值類(lèi)型和引用類(lèi)型成員的值

 static void Main(string[] args)
    {
      Room room1 = new Room(60);
      Film film1 = new Film("家園防線");
      Cinema cinema1 = new Cinema(room1, film1);
      Cinema cinema2 = (Cinema)cinema1.Clone1();
      Console.WriteLine("拷貝之前,結(jié)構(gòu)成員的字段值為{0},引用類(lèi)型成員的字段值為{1}", cinema1._film._name,cinema1._room._maxSeat);
 
      Console.WriteLine("拷貝之后,新的結(jié)構(gòu)成員的字段值為{0},引用類(lèi)型成員的字段值為{1}", cinema2._film._name, cinema2._room._maxSeat);
 
      //修改拷貝之前引用類(lèi)型的字段值
      cinema1._film._name = "極品飛車(chē)";
      cinema1._room._maxSeat = 80;
 
      Console.WriteLine("修改之后,結(jié)構(gòu)成員的字段值為{0},引用類(lèi)型成員的字段值為{1}", cinema1._film._name, cinema1._room._maxSeat);
      Console.WriteLine("修改之后,新的結(jié)構(gòu)成員的字段值為{0},引用類(lèi)型成員的字段值為{1}", cinema2._film._name, cinema2._room._maxSeat);
 
      Console.ReadKey();
    }

結(jié)果:

 

分析:

深拷貝后,兩個(gè)對(duì)象的引用成員已經(jīng)分離,改變?cè)葘?duì)象引用類(lèi)型成員的值并不會(huì)對(duì)復(fù)制對(duì)象的引用類(lèi)型成員值造成影響。

相關(guān)文章

最新評(píng)論