【问题标题】:Code confusion - why does one work, but not the other?代码混乱 - 为什么一个有效,而另一个无效?
【发布时间】:2023-03-17 06:45:01
【问题描述】:

注意:这已经可以正常工作了,但我正在尝试理解为什么它会以这种方式工作,而不是另一种。

我有一个带有动态放置图像的 WinForm (C#),如下所示:

现在,如果您单击“Napred”按钮,这些图像应该被删除(除其他外),我最初使用的是:

foreach(Control ctrl in Controls)
    if(ctrl is PictureBox) ctrl.Dispose();

for(int i = 0; i < Controls.Count; i++)
    if(Controls[i] is PictureBox) Controls[i].Dispose();

现在如果我运行它,我会得到:

但如果我只是将 for 语句更改为向后发送,它有效

for(int i = Controls.Count - 1; i >= 0; i--)
    if(Controls[i] is PictureBox) Controls[i].Dispose();

(我不会再上传一张图片,但它会删除所有元素(我只得到最后剩下的按钮))

谁能告诉我为什么一个有效,而另一个无效

编辑:如果出现调试错误,我在 Windows 10 上使用 VS2015 社区版(?)

【问题讨论】:

  • 如果您有一个包含 10 个项目的数组,然后删除 Item1,Item2 将成为新的 Item1,您将剩下 9 个项目。处理数组项的标准方法是向后逐步处理。
  • 可能对其他方法感兴趣:stackoverflow.com/questions/7340757/…
  • 为什么不用Remove方法?
  • @SergiiZhevzhyk 我做了,几乎相同的结果,但我在其他地方读到 Remove() 没有正确处理元素(内存方面),这是一个更好的解决方案。
  • @NemanjaT 我完全同意所有资源都应该妥善处理。我可能会从收藏中删除图片,然后将其丢弃。

标签: c# winforms for-loop picturebox


【解决方案1】:

您正在尝试更改您正在迭代的列表,这当然会更改此列表的索引,因此索引 1 处的内容现在位于索引 0 处。

通过从数组的末尾删除(即反向),以前的索引将始终相同。

正如 Matthew Watson 的评论中所述,注意这一点也很重要:

Control.Dispose() 是特殊的,它将从父容器的控件列表中删除控件。

这不是大多数 Dispose 方法的默认行为,因此您在使用 Dispose 时不会总是发现这种行为

【讨论】:

  • 我明白,这就是为什么每个第二个元素都被删除的原因。感谢您解决这个问题!我根本没想到!
  • 我认为您应该清楚他如何更改他正在迭代的列表,因为仅通过检查代码他并没有直接从列表中删除项目。答案是Control.Dispose() 是特殊的,它将从父容器的Controls 列表中移除控件。
  • @MatthewWatson - 非常正确,我试图保持这个通用性参考列表本身
  • 但是以这种方式迭代通常会很好,按顺序在列表中放置项目,因为它不会更改列表中项目的索引。正在迭代的是 Controls 属性,这一点非常重要。仅对列表中的项目调用 Dispose() 通常不会更改列表本身。
  • @MatthewWatson - 我现在已经在我的回答中包含了您的部分评论,我试图在 msdn 或 developersource 中找到对此的正确引用,但无法找到。希望这没问题!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-03
  • 2023-03-21
  • 1970-01-01
相关资源
最近更新 更多