问题描述
我想为撤消/重做制作备份列表, 但是我修改了原List中的对象后,BackUp List中的对象就会发生变化。 我该如何处理这个问题? “const”、“in”似乎不起作用。
private List<geminiFileStruct> BackUpForUndoRedo(List<geminiFileStruct> gfl,ToolStripMenuItem tm)
{
var li =
(from i in gfl
select i).ToList();
tm.Enabled = true;
return li;
}
抱歉,以前是结构体。引起一些问题,我换班。 struct 可以有 Get/Set 吗??? C# 的新手。
解决方法
您需要的是列表的所谓深拷贝:
备份列表中的项目将是原始项目的克隆 列表。具有相同属性的全新项目实例。
不是浅拷贝:
“仅”引用原始列表中项目的备份列表。这会导致 将备份列表中的A项更改为备份列表中的A项 原始列表,因为它们引用了相同的项目?。
查看 this SO post 或以下任何网页:tutorial 1、tutorial 2。
深度复制不是一种简单的编程技术,正如您会发现的那样。但在正确的上下文中,在正确的假设下,它可以安全地完成。
注意
正如@Llama 指出的那样,在执行 new List<TStruct>(originalListWithStructs)
时,自动 获得了具有结构的列表的深层副本。 Struct 是一种值类型,与引用类型相比表现不同。
虽然 Bernoulli IT 描述了使用浅拷贝的实际问题,但我想为撤消/重做提供更多背景知识。撤销/重做有两种主要方法
-
Memento pattern。在对对象进行更改之前,会创建一个备忘录,可用于恢复所述对象的状态。这可以应用于整个应用程序,即在任何更改之前,应用程序状态被序列化,就像用户保存到文件一样。然后可以恢复此序列化状态,就像加载文件时一样。假设有一个函数可以保存到文件,并且这表示应用程序状态。请注意,序列化/反序列化会隐式地创建一个深拷贝。
-
Command pattern。每个更改都应该由一个命令完成,该命令知道如何撤消更改。这样做的一个缺点是,确保所有操作都正确生成这些对象可能会很复杂。