【问题标题】:How to get a backup List?如何获取备份列表?
【发布时间】:2021-07-15 08:59:00
【问题描述】:

我想为撤消/重做制作备份列表, 但是在我修改了原始列表中的对象后,备份列表中的对象会发生变化。 我该如何处理这个问题? "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#。

【问题讨论】:

  • 如果备份列表中的项目在原始列表发生更改时被修改,这表明GeminiFileStruct 的命名非常糟糕,实际上是引用类型(类),而不是结构.这反过来意味着两个列表当前都包含对同一组对象的引用,而不是不同的对象。
  • 你不需要var li = (from i in gfl select i).ToList(); - 你可以简单地写var li = gfl.ToList();。请根据 Damien 的评论提供GeminiFileStruct 的定义。
  • @Damien_The_Unbeliever 对不起,它曾经是 struct。出了点问题,我换班了。
  • @Llama 当我阅读 OP 的问题时,需要的是原始项目的克隆列表(他想更改备份列表中的项目而不影响原始列表中的项目)。这是深拷贝与浅拷贝的例子。
  • @BernoulliIT Here is an example for your own leanring。请注意 struct 的行为方式与引用类型的行为方式?请注意如何使用 struct 开箱即用地获取深层副本?

标签: c# list constants


【解决方案1】:

虽然 Bernoulli IT 描述了使用浅拷贝的实际问题,但我想为撤消/重做提供更多背景知识。撤销/重做主要有两种方法

  1. Memento pattern。在对对象进行更改之前,会创建一个memento,用于恢复所述对象的状态。这可以应用于整个应用程序,即在任何更改之前,应用程序状态被序列化,就像用户保存到文件一样。然后可以恢复此序列化状态,就像加载文件时一样。假设有一个保存到文件的函数,并且这代表了应用程序的状态。请注意,序列化/反序列化将隐式创建深层副本。

  2. Command pattern。每个更改都应由知道如何撤消更改的命令 完成。这样做的一个缺点是,确保所有操作都正确生成这些对象可能很复杂。

【讨论】:

    【解决方案2】:

    您需要的是列表的所谓深拷贝

    备份列表中的项目将是原始项目的克隆 列表。具有相同属性的项目的全新实例。

    不是浅拷贝

    “仅”引用原始列表中的项目的备份列表。这会导致 将备份列表中的项目 A 更改为备份列表中的项目 A 原始列表,因为它们引用了相同的项目 ?。

    查看this SO post 或以下任何网页:tutorial 1tutorial 2

    深度复制不是一种简单的编程技术,你会发现。但在正确的假设和正确的背景下,它可以安全地完成。

    注意

    正如@Llama 指出的那样,在执行new List&lt;TStruct&gt;(originalListWithStructs) 时,自动获得了具有结构的列表的深层副本。 Struct 是一种值类型,其行为与引用类型相比有所不同。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-06-18
      • 1970-01-01
      • 1970-01-01
      • 2018-06-03
      • 1970-01-01
      • 1970-01-01
      • 2020-06-16
      相关资源
      最近更新 更多