浅谈C#中List对象的深度拷贝问题
一、List<T>对象中的T是值类型的情况(int类型等)
对于值类型的List直接用以下方法就可以复制:
List<T>oldList=newList<T>(); oldList.Add(..); List<T>newList=newList<T>(oldList);
二、List<T>对象中的T是引用类型的情况(例如自定义的实体类)
1、对于引用类型的List无法用以上方法进行复制,只会复制List中对象的引用,可以用以下扩展方法复制:
staticclassExtensions { publicstaticIList<T>Clone<T>(thisIList<T>listToClone)whereT:ICloneable { returnlistToClone.Select(item=>(T)item.Clone()).ToList(); } //当然前题是List中的对象要实现ICloneable接口 }
2、另一种用序列化的方式对引用对象完成深拷贝,此种方法最可靠
publicstaticTClone<T>(TRealObject) { using(StreamobjectStream=newMemoryStream()) { //利用System.Runtime.Serialization序列化与反序列化完成引用对象的复制 IFormatterformatter=newBinaryFormatter(); formatter.Serialize(objectStream,RealObject); objectStream.Seek(0,SeekOrigin.Begin); return(T)formatter.Deserialize(objectStream); } }
3、利用System.Xml.Serialization来实现序列化与反序列化
publicstaticTClone<T>(TRealObject) { using(Streamstream=newMemoryStream()) { XmlSerializerserializer=newXmlSerializer(typeof(T)); serializer.Serialize(stream,RealObject); stream.Seek(0,SeekOrigin.Begin); return(T)serializer.Deserialize(stream); } }
三、对上述几种对象深拷贝进行测试
测试如下:
usingSystem; usingSystem.Collections.Generic; usingSystem.Collections; usingSystem.Linq; usingSystem.Text; usingSystem.IO; usingSystem.Runtime.Serialization; usingSystem.Runtime.Serialization.Formatters.Binary; namespaceLINQ { [Serializable] publicclasstt { privatestringname=""; publicstringName { get{returnname;} set{name=value;} } privatestringsex=""; publicstringSex { get{returnsex;} set{sex=value;} } } classLINQTest { publicstaticTClone<T>(TRealObject) { using(StreamobjectStream=newMemoryStream()) { IFormatterformatter=newBinaryFormatter(); formatter.Serialize(objectStream,RealObject); objectStream.Seek(0,SeekOrigin.Begin); return(T)formatter.Deserialize(objectStream); } } publicstaticvoidMain() { List<tt>lsttt=newList<tt>(); tttt1=newtt(); tt1.Name="a1"; tt1.Sex="20"; lsttt.Add(tt1); List<tt>l333=newList<tt>(); l333.Add(Clone<tt>(lsttt[0])); l333[0].Name="333333333"; } } }
以上这篇浅谈C#中List