C# シャロー コピーとディープ コピーの例の分析

高洛峰
リリース: 2017-01-19 11:41:50
オリジナル
1591 人が閲覧しました

場合によっては、データベースからデータを読み取ってオブジェクトを埋めたり、ハードディスクからファイルを読み取ってオブジェクトを埋めたりする必要がありますが、これには比較的時間がかかります。今回はオブジェクトをコピーすることを考えます。この記事では、C# のシャロー コピーとディープ コピーの使用法を例の形で分析します。詳細は以下のとおりです:

1. 浅いコピー

1. 「浅いコピー」とは:

オブジェクトをコピーするとき、オブジェクトの値型メンバーはそれ自身をコピーし、オブジェクトの参照型メンバーの場合はオブジェクトのみをコピーします。マネージド ヒープ上のオブジェクト インスタンスを指す参照がコピーされます。

2. 参照型のクラスメンバーと値型の構造体メンバーを含むオブジェクトがあります。

Cinema には参照型メンバー Room と値型メンバー 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(); //对引用类型实施浅复制
  }
}
ログイン後にコピー

3. コピー後の効果をテストします

①コピー前に元のオブジェクトの値型と参照型のメンバーの値を出力します
②元のオブジェクトをコピーし、値型の値を出力しますコピーしたオブジェクトの値型と参照型のメンバーを再度出力します
③ 元のオブジェクトの値を変更し、元のオブジェクトの値型と参照型のメンバーを再度出力します
④ コピーしたオブジェクトの値型と参照型のメンバーを再度出力します

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("拷贝之前,结构成员的字段值为{0},引用类型成员的字段值为{1}", cinema1._film._name,cinema1._room._maxSeat);
 
  Console.WriteLine("拷贝之后,新的结构成员的字段值为{0},引用类型成员的字段值为{1}", cinema2._film._name, cinema2._room._maxSeat);
 
  //修改拷贝之前引用类型的字段值
  cinema1._film._name = "极品飞车";
  cinema1._room._maxSeat = 80;
 
  Console.WriteLine("修改之后,结构成员的字段值为{0},引用类型成员的字段值为{1}", cinema1._film._name, cinema1._room._maxSeat);
  Console.WriteLine("修改之后,新的结构成员的字段值为{0},引用类型成员的字段值为{1}", cinema2._film._name, cinema2._room._maxSeat);
 
  Console.ReadKey();
}
ログイン後にコピー

分析:

浅いコピーの重要なポイントは参照型です。コピーされるのはオブジェクト参照であり、マネージド ヒープ上のオブジェクト インスタンスを指します。元の対応する参照型の値を変更すると、コピーされたオブジェクトに影響します。

2.ディープコピー

1.「ディープコピー」とは

参照メンバーが指すオブジェクトをコピーし、元のオブジェクトインスタンスに含まれるデータをマネージドヒープ上に割り当てます。マネージド ヒープの例。

2. 各オブジェクトのメンバーをコピーすることによるディープコピー

public object Clone()
{
  Room room = new Room();
  room._maxSeat = this._room._maxSeat;//复制当前引用类型成员的值到新对象
  Film film = this._film; //值类型直接赋值
  Cinema cinema = new Cinema(room, film);
  return cinema;
}
ログイン後にコピー

3. シリアル化とデシリアライズによってディープコピーを行うこともできます

public object Clone1()
{
  BinaryFormatter bf = new BinaryFormatter();
  MemoryStream ms = new MemoryStream();
  bf.Serialize(ms, this); //复制到流中
  ms.Position = 0;
  return (bf.Deserialize(ms));
}
ログイン後にコピー

4. シリアル化とデシリアライズを伴うディープコピーですが、すべてのクラスが[シリアル化可能]である必要があります。テストコードは以下の通りです:

[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(); //对引用类型实施浅复制
  //}
 
  //深拷贝 对每个对象成员进行复制
  public object Clone()
  {
    Room room = new Room();
    room._maxSeat = this._room._maxSeat;//复制当前引用类型成员的值到新对象
    Film film = this._film; //值类型直接赋值
    Cinema cinema = new Cinema(room, film);
    return cinema;
  }
 
  //使用序列化和反序列化进行复制
  public object Clone1()
  {
    BinaryFormatter bf = new BinaryFormatter();
    MemoryStream ms = new MemoryStream();
    bf.Serialize(ms, this); //复制到流中
    ms.Position = 0;
    return (bf.Deserialize(ms));
  }
}
ログイン後にコピー

5. コピー後の効果をテストします

①コピーする前に元のオブジェクトの値型と参照型のメンバーの値を出力します

②元のオブジェクトにコピーしてコピーしたオブジェクトの値型と参照型のメンバーの値を出力します
③ 元のオブジェクトの値を変更し、再度元のオブジェクトの値型と参照型のメンバーの値を出力します
④コピーされたオブジェクトの値型と参照型のメンバーの値を再度

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("拷贝之前,结构成员的字段值为{0},引用类型成员的字段值为{1}", cinema1._film._name,cinema1._room._maxSeat);
 
     Console.WriteLine("拷贝之后,新的结构成员的字段值为{0},引用类型成员的字段值为{1}", cinema2._film._name, cinema2._room._maxSeat);
 
     //修改拷贝之前引用类型的字段值
     cinema1._film._name = "极品飞车";
     cinema1._room._maxSeat = 80;
 
     Console.WriteLine("修改之后,结构成员的字段值为{0},引用类型成员的字段值为{1}", cinema1._film._name, cinema1._room._maxSeat);
     Console.WriteLine("修改之后,新的结构成员的字段值为{0},引用类型成员的字段值为{1}", cinema2._film._name, cinema2._room._maxSeat);
 
     Console.ReadKey();
   }
ログイン後にコピー

結果:

C# シャロー コピーとディープ コピーの例の分析

分析:

ディープコピー後、2つのオブジェクトの参照メンバーが分離されました。元のオブジェクトの参照型メンバーの値は、コピーされたオブジェクトの参照型メンバーの値には影響しません。

C# の浅いコピーと深いコピーの例の分析に関連するその他の記事については、PHP 中国語 Web サイトに注目してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!