場合によっては、データベースからデータを読み取ってオブジェクトを埋めたり、ハードディスクからファイルを読み取ってオブジェクトを埋めたりする必要がありますが、これには比較的時間がかかります。今回はオブジェクトをコピーすることを考えます。この記事では、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)); }
[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)); } }
②元のオブジェクトにコピーしてコピーしたオブジェクトの値型と参照型のメンバーの値を出力します
③ 元のオブジェクトの値を変更し、再度元のオブジェクトの値型と参照型のメンバーの値を出力します
④コピーされたオブジェクトの値型と参照型のメンバーの値を再度
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(); }