一、浅拷贝
1.什么是"浅拷贝":
当针对一个对象前拷贝的时刻,关于对象的值范例成员,会复制其自身,关于对象的援用范例成员,仅仅复制对象援用,这个援用指向托管堆上的对象实例。
2.有一个对象,包括援用范例的类成员和值范例的struct成员
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(); }
剖析:
浅拷贝症结点是对援用范例拷贝的是对象援用,这个援用指向托管堆上的对象实例。转变原对应援用范例的值,会影响到复制对象。
二、深拷贝
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],测试代码以下:
[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#浅拷贝和深拷贝实例剖析相干文章请关注ki4网!