深度復(fù)制與淺表復(fù)制的區(qū)別在于,淺表復(fù)制只復(fù)制值類型的值,而對(duì)于實(shí)例所包含的對(duì)象依然指向原有實(shí)例。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
class Program { [Serializable] public class Car { public string name; public Car( string name) { this .name = name; } } [Serializable] public class Person:ICloneable { public int id; public string name; public Car car; public Person() { } public Person( int id, string name, Car car) { this .id = id; this .name = name; this .car = car; } public Object Clone() //實(shí)現(xiàn)ICloneable接口,達(dá)到淺表復(fù)制。淺表復(fù)制與深度復(fù)制無(wú)直接有關(guān)系。 對(duì)外提供一個(gè)創(chuàng)建自身的淺表副本的能力 { return this .MemberwiseClone(); } } //要復(fù)制的實(shí)例必須可序列化,包括實(shí)例引用的其它實(shí)例都必須在類定義時(shí)加[Serializable]特性。 public static T Copy<T>(T RealObject) { using (Stream objectStream = new MemoryStream()) { //利用 System.Runtime.Serialization序列化與反序列化完成引用對(duì)象的復(fù)制 IFormatter formatter = new BinaryFormatter(); formatter.Serialize(objectStream, RealObject); objectStream.Seek(0, SeekOrigin.Begin); return (T)formatter.Deserialize(objectStream); } } static void Main( string [] args) { Person p1 = new Person(1, "Scott" , new Car( "寶馬" )); Console.WriteLine( "原始值:P1:id={0}----------->name={1}------>car={2}" , p1.id, p1.name, p1.car.name); Person p2 = Copy<Person>(p1); //克隆一個(gè)對(duì)象 Person p3 = p1.Clone() as Person; //淺表復(fù)制 Console.WriteLine( "改變P1的值" ); p1.id = 2; p1.name = "Lacy" ; p1.car.name = "紅旗" ; Console.WriteLine( "P1:id={0}----------->name={1}------>car={2}" , p1.id, p1.name, p1.car.name); Console.WriteLine( "深度復(fù)制:P2:id={0}----------->name={1}------>car={2}" , p2.id, p2.name, p2.car.name); Console.WriteLine( "淺表復(fù)制:P3:id={0}----------->name={1}------>car={2}" , p3.id, p3.name, p3.car.name); Console.ReadKey(); } |
運(yùn)行結(jié)果:
一、List<T>對(duì)象中的T是值類型的情況(int 類型等)
對(duì)于值類型的List直接用以下方法就可以復(fù)制:
1
2
3
|
List<T> oldList = new List<T>(); oldList.Add(..); List<T> newList = new List<T>(oldList); |
二、List<T>對(duì)象中的T是引用類型的情況(例如自定義的實(shí)體類)
1、對(duì)于引用類型的List無(wú)法用以上方法進(jìn)行復(fù)制,只會(huì)復(fù)制List中對(duì)象的引用,可以用以下擴(kuò)展方法復(fù)制:
1
2
3
4
5
6
7
8
|
static class Extensions { public static IList<T> Clone<T>( this IList<T> listToClone) where T: ICloneable { return listToClone.Select(item => (T)item.Clone()).ToList(); } //<SPAN style="COLOR: #000000">當(dāng)然前題是List中的對(duì)象要實(shí)現(xiàn)ICloneable接口</SPAN> } |
2、另一種用序列化的方式對(duì)引用對(duì)象完成深拷貝,此種方法最可靠
1
2
3
4
5
6
7
8
9
10
11
12
|
public static T Clone<T>(T RealObject) { using (Stream objectStream = new MemoryStream()) { //利用 System.Runtime.Serialization序列化與反序列化完成引用對(duì)象的復(fù)制 IFormatter formatter = new BinaryFormatter(); formatter.Serialize(objectStream, RealObject); objectStream.Seek(0, SeekOrigin.Begin); return (T)formatter.Deserialize(objectStream); } } |
3、利用System.Xml.Serialization來(lái)實(shí)現(xiàn)序列化與反序列化
1
2
3
4
5
6
7
8
9
10
|
public static T Clone<T>(T RealObject) { using (Stream stream= new MemoryStream()) { XmlSerializer serializer = new XmlSerializer( typeof (T)); serializer.Serialize(stream, RealObject); stream.Seek(0, SeekOrigin.Begin); return (T)serializer.Deserialize(stream); } } |
以上這篇C#復(fù)制和深度復(fù)制的實(shí)現(xiàn)方法就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持服務(wù)器之家。