3

ImageList 应创建插入其中的所有图像的副本。因此,在将原件添加到列表后处理它们应该是安全的。

为什么以下测试用例会失败?

Bitmap test = new Bitmap(128, 128);
ImageList il = new ImageList();

il.Images.Add(test);
Assert.AreEqual(1, il.Images.Count); // OK, image has been inserted
test.Dispose(); // now let's dispose the original
try
{
    var retrievalTest = il.Images[0];
}
catch (ArgumentException) // ... but this Exception happens!
{
}

Assert.AreEqual(1, il.Images.Count); // and this will fail

这里似乎发生了这样的事情:当尝试检索图像时,ImageList 发现原始图像已被释放,并将其从 ImageList 中删除。

为什么会发生这种情况,我认为 ImageList 应该创建图像的副本?

4

2 回答 2

6

是的,ImageList 创建位图的副本。但是您的测试代码与 .NET 框架中常见的著名的惰性初始化模式相冲突。重要的是它何时创建副本。只有在必要时才会这样做。对您的代码进行一些小改动以加快速度:

il.Images.Add(test);
var dummy = il.Handle;     // <== NOTE: added
test.Dispose();            // no problem

你会发现处理不再是问题。

不知道如何在这里给出适当的建议,代码太综合了。这通常工作得很好,当 ImageList 的消费者开始使用它的位图、Treeview 或 ListView 时,它会生成副本。一般来说,避免使用 ImageList 作为集合对象,它不是用来完成这项工作的。将视图与模型分开,您就不会遇到麻烦。

于 2013-07-14T13:13:53.057 回答
1

ImageList 应创建插入其中的所有图像的副本。

我在文档中没有看到任何迹象,确实如此。所以简单的答案是:你的假设是错误的。

于 2013-07-14T12:25:39.700 回答