当我在lstCopy中创建原始列表lstStudent的副本并将lstCopy发送到修改函数时,lstStudent也会被修改。我想保持这个列表不被修改。
List<Student> lstStudent = new List<Student>();
Student s = new Student();
s.Name = "Akash";
s.ID = "1";
lstStudent.Add(s);
List<Student> lstCopy = new List<Student>(lstStudent);
Logic.ModifyList(lstCopy);
// "Want to use lstStudent(original list) for rest part of the code"
public static void ModifyList(List<Student> lstIntegers) {
foreach (Student s in lstIntegers) {
if (s.ID.Equals("1")) {
s.ID = "4"; s.Name = "APS";
}
}
}
答案 0 :(得分:3)
使用二进制格式化程序,您也可以在没有可克隆接口的情况下实现此目的: 注意:作为对象图的一部分的所有类必须标记为Serializable。
void Main()
{
var student1=new Student{Name="Bob"};
var student2=new Student{Name="Jim"};
var lstStudent=new List<Student>();
lstStudent.Add(student1);
lstStudent.Add(student2);
var lstCopy=new List<Student>(lstStudent);
var clone=Clone(lstStudent);
student1.Name="JOE";
lstCopy.Dump();
lstStudent.Dump();
clone.Dump();
}
public List<Student> Clone(List<Student> source)
{
BinaryFormatter bf=new BinaryFormatter();
using(var ms=new MemoryStream())
{
bf.Serialize(ms,source);
ms.Seek(0,0);
return (List<Student>)bf.Deserialize(ms);
}
}
[Serializable]
public class Student
{
public string Name { get; set; }
}
输出:
5List<Student> (2 items) 4
Name
JOE
Jim
5List<Student> (2 items) 4
Name
JOE
Jim
5List<Student> (2 items) 4
Name
Bob
Jim
代码格式化为转储到LINQPad
编辑:
在无法实现ICloneable
的情况下,这是一个选项。适用时,代码接口。换句话说,您可以在学生对象上实现ICloneable
并使用BinaryFormatter
方法中的Clone()
逻辑;但是,作为开发人员,您可以选择自己决定要执行的操作。选项不一定是建议,建议并不总是一种选择。有些时候你必须完成任务所需的工作,这就是选项发挥作用的地方。
这是一种广泛接受的深度克隆方法: How do you do a deep copy of an object in .NET (C# specifically)?
答案 1 :(得分:2)
我会看看ICloneable。你所追求的是一个&#34;深拷贝&#34;。这篇文章中有很多好消息:
答案 2 :(得分:1)
使用LINQ
复制列表的另一种快捷方法List<student> oldList = new List<student> { new student{
id=122,
name="John"} };
IEnumerable<student> copy= oldList.Select(item => new student{
id = item.id,
name = item.name });
List<student> newList= new List<student>(copy);
但最好的选择仍然是实施ICloneable来深度复制你的对象
答案 3 :(得分:0)
如果您的Student
类型是类(引用类型),则列表将仅包含对这些实例的引用。这意味着当您复制列表时,复制的列表也将只包含仍指向相同Student
实例的引用。通过复制列表,您只需复制引用但不复制实例。副本之后的内容是这样的:
List 1 List 2 instance S1
ref to S1 ref to S1 Name: Akash
ref to S2 ref to S2 ...
... ...
因此,如果您执行list1[0].Name = "Jim"
之类的操作,您将更新实例S1
,并且您将看到两个列表中的更改,因为两个列表都引用了同一组实例。
您需要做的是创建一个不仅包含此情况下的列表,而且还包含里面的所有对象的克隆 - 您还需要克隆所有Student
个对象。这称为深拷贝。像这样:
class StudentList : List<Student>, ICloneable
{
public object Clone ()
{
StudentList oNewList = new StudentList ();
for ( int i = 0; i < Count; i++ )
{
oNewList.Add ( this[i].Clone () as Student );
}
return ( oNewList );
}
}
你这样称呼:
StudentList oClonedList = lstStudent.Clone () as StudentList;
您还需要通过实施ICloneable
接口来克隆Student
类。
不要忘记,在此之后,您将拥有2个单独的列表和2个独立的Student
个对象 - 修改一个Student
实例对您其他人的学生没有任何影响列表。
答案 4 :(得分:0)
您需要列表的深层副本。现在,这是一个浅薄的副本。您只有两个对同一变量的引用。没有简单的方法可以像C ++这样的语言在C#中获得深层复制。获取深层副本的一种方法是序列化和反序列化第一个列表。以下是获取对象深层副本的模板化函数。
public static T getDeepCopy<T>( T objectToCopy )
{
T temp;
using ( MemoryStream ms = new MemoryStream() )
{
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize( ms, objectToCopy );
ms.Position = 0;
temp = (T)formatter.Deserialize( ms );
}
return temp;
}
您还需要包含这些命名空间:
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
然后您可以像这样调用函数:
lstCopy = getDeepCopy<List<Student>>(lstStudents);