ImageList中:处置原始图像从列表中移除移除、图像、原始、列表中

2023-09-06 15:32:21 作者:或許、莪鬧够了

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

ImageList should create a copy of all images that are inserted into it. Therefore it should be safe to dispose the originals after adding them to the list.

为什么下面的测试用例失败?

Why does the following testcase fail?

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中移除

What seems to happen here is this: When trying to retrieve the image, the ImageList discovers that the original has been disposed, and removes it from the ImageList.

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

Why is that happen, I thought the ImageList is supposed to create a copy of the image?

推荐答案

是的,ImageList中创建位图的副本。但是,你的测试code运行触犯了著名的延迟初始化模式是如此常见的.NET Framework。重要的是在它创建的副本。这是做只有当它必须如此。让您的code小改快点说了:

Yes, ImageList creates a copy of the bitmap. But your test code runs afoul of the famous lazy initialization pattern that's so common in the .NET framework. What matters is when it creates the copy. Which is does only when it has to. Make a small change in your code to hurry that up:

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

你会看到,产权处置是不再是一个问题。

And you'll see that disposing is no longer a problem.

不知道怎么在这里给予适当的意见,code是太合成。这在一般的工作做得不够好,ImageList中进行复制的消费者开始使用它的位图,树视图或ListView时。在一般情况下,应避免使用的ImageList作为一个集合对象,它不是为了做这项工作。视图从模型中分离,你会远离麻烦。

Not sure how to give proper advice here, the code is too synthetic. This in general works well enough, ImageList makes the copy when its consumers start using its bitmaps, Treeview or ListView. In general, avoid using ImageList as a collection object, it wasn't made to do that job. Separate the view from the model and you'll stay out of trouble.