什么时候需要Dispose?
当你有这样的代码时:
Bitmap bmp = new Bitmap ( 100, 100 );
Graphics g = Graphics.FromImage ( bmp );
Pen p = new Pen ( Color.FromArgb ( 128, Color.Blue ), 1 );
Brush b = new SolidBrush ( Color.FromArgb ( 128, Color.Blue ) );
g.FillEllipse ( b, 0, 0, 99, 99 );
g.FillRegion ( b, pictureBox1.Region );
pictureBox1.BackColor = Color.Transparent;
pictureBox1.Image = bmp;
你必须扔掉笔和画笔吗? bmp 和 g 怎么样?
我的主要问题是,如果要手动处理它们,为什么不在它们超出范围后立即处理? 如果您不手动处理它们,会发生这种情况吗? 是不是延迟导致人们手动执行此操作?
When you have code like:
Bitmap bmp = new Bitmap ( 100, 100 );
Graphics g = Graphics.FromImage ( bmp );
Pen p = new Pen ( Color.FromArgb ( 128, Color.Blue ), 1 );
Brush b = new SolidBrush ( Color.FromArgb ( 128, Color.Blue ) );
g.FillEllipse ( b, 0, 0, 99, 99 );
g.FillRegion ( b, pictureBox1.Region );
pictureBox1.BackColor = Color.Transparent;
pictureBox1.Image = bmp;
Do you have to dispose the pen and brush? What about bmp and the g?
My main question is, if these were to be disposed manually, why don't they get disposed as soon as they get out of the scope? Is that what would happen, if you didn't dispose them manually? Is it the delay that makes people do this manually?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
是的,您必须处理它们 - 不仅仅是笔和画笔,还有位图和图形。
当它们超出范围时,它们不会被释放,因为变量本身是引用,而不是对象,并且 C# 编译器不知道所有权是否仍然属于这些引用(例如
FillEllipse
理论上,可以记住它给出的引用,并在稍后的某个时刻尝试使用它 - 请记住语言编译器没有任何库语义的特殊知识!)。如果您想指示所有权仅限于该范围,请使用
using
语句:这将使编译器根据需要自动插入对
Dispose
的调用,确保所有对象一旦离开相应的using
范围(无论是正常情况下,通过诸如return
或break
之类的控制传输,还是异常),就会被处置。如果您有 C++ 背景,C# 中的
using
直接类似于const std::auto_ptr
,只不过它是一种语言构造,并且只能用于局部变量(即不适用于类字段)。Yes, you have to dispose them - not just pen and brush, but also
Bitmap
andGraphics
.They don't get disposed when they're out of scope because the variables themselves are references, not objects, and C# compiler doesn't know whether the ownership still belongs to those references or not (e.g.
FillEllipse
could, in theory, remember the reference it's given, and try to use it at some later moment - remember that language compiler doesn't have any special knowledge of library semantics!).If you want to indicate that ownership is restricted to that scope, you use the
using
statement:This will make the compiler insert calls to
Dispose
automatically as needed, ensuring that all objects are disposed once the correspondingusing
scope is left (whether normally, by control transfer such asreturn
orbreak
, or an exception).If you come from a C++ background,
using
in C# is directly analogous to aconst std::auto_ptr
, except that it's a language construct here, and can only be used for local variables (i.e. not for class fields).我知道其他人已经在这里放置了代码示例,但我开始了,所以我会完成:
我总是在代码中使用
using
因为它会自动在您的对象上调用Dispose()
,即使using
块中引发了异常。 我在 SharePoint 项目中经常使用它(但那是另一个故事了......)。I know other people have put code examples here, but I started so I'll finish:
I always use
using
in my code since it callsDispose()
on your object automatically, even if there is an exception raised in theusing
block. I use it a lot for SharePoint projects (but that's another story...).如果正确使用一次性模式,
Dispose
并不是绝对必要的——它将在对象完成时调用,因此您不会泄漏资源或任何东西。但是,在使用完对象后立即调用
Dispose
是一种好习惯,因为一次性对象通常直接控制通常有限的本机资源。 对象通常不会立即完成/收集,因此一旦您不再使用该对象,这些资源就会闲置、浪费。 处置会立即释放这些资源,以便程序的其他部分(或者在某些情况下,其他程序)可以使用它们。请注意,
using
块会在您使用完对象后自动处置该对象,这就是为什么您很少在using
中看到Dispose
的原因堵塞。简短版本:如果对象实现了
IDisposable
,并且您的代码创建了它(即:如果它不是像Pens.Blue
这样的系统对象,或者Graphics你在
OnPaint
等中传递),当你完全完成它时,它应该被处置——无论是通过调用Dispose
,还是通过调用其他一些方法指定调用Dispose
(Close
是常见的),或者通过使用using
块。 您不必必须处置它,但您几乎总是应该这样做。If the disposable pattern is used correctly,
Dispose
is not strictly necessary -- it will be called when the object is finalized, so you won't leak resources or anything.However, it's good manners to call
Dispose
as soon as you're done using the object, as disposables often directly control native resources which are usually limited. Objects don't normally get finalized/collected right away, so those resources are just hanging around, wasted, once you're not using the object anymore. Disposing frees those resources immediately, so they can be used by other parts of the program (or in some cases, by other programs).Note, a
using
block automatically disposes the object when you're done with it, which is why you rarely if ever seeDispose
within ausing
block.Short version: If the object implements
IDisposable
, and your code created it (ie: if it's not a system object likePens.Blue
, or theGraphics
you get passed inOnPaint
etc), it should be disposed when you're totally done with it -- whether by callingDispose
, or by calling some other method that's specified to callDispose
(Close
is a common one), or by using ausing
block. You don't have to dispose it, but you almost always should.C# 不会在事物超出范围后立即“破坏”或处置它们。
这些类很可能会自动释放它们在特殊的
Finalizer
方法中持有的非托管资源,当它们在运行后的不确定时间进行垃圾收集时,将调用该方法。超出范围。但依赖它就等于依赖一些你无法控制的事情,而且可能暂时不会发生。
如果该类实现了 IDisposable,最佳实践是您在某处手动调用
Dispose()
,或者最好将其包装在using
块中。 这样您就可以确定:C# doesn't "destruct" or dispose of things as soon they go out of scope.
Those classes will most likely automatically free the unmanaged resources that they hold on to in their special
Finalizer
method, which will be called when they are garbage collected at an indeterminate time after going out of scope.But to rely on that is to rely on something that is out of your control, and might not happen for a while.
If the class implements IDisposable, best practice is for you to manually call
Dispose()
somewhere, or preferably wrap it in ausing
block. That way you can be sure that:是的,bmp、g、b 和 p 都是 IDisposable,您应该将它们全部 Dispose() 。 最好使用
using() {}
块。但也有例外,当您使用
Pen p2 = Pens.Blue;
时,您不应该丢弃 p2。 它被称为库存项目。 Brushes.Black 等也是如此。至于原因,对于所有一次性类都是相同的。 .Net 不使用引用计数,因此当引用超出范围时,不会(不能)立即采取行动。
将其留给垃圾收集器最终将释放它们,但效率(非常)低。 我知道一个 ASP.NET (!) 应用程序由于缺少图形句柄而失败,因为没有及时处理它们。 它正在生成图像。
Yes, bmp, g, b and p are all IDisposable, you should Dispose() all of them. Preferably by using
using() {}
blocks.There are exceptions, when you use
Pen p2 = Pens.Blue;
yous should not dispose p2. It's called a stock item. The same for Brushes.Black etc.As for the why, it's the same for all disposable classes. .Net does not use reference counting so there is no (cannot be) an immediate action when a reference goes out of scope.
And leaving it to the Garbage collector will eventually free them but it is (very) inefficient. I know of an ASP.NET (!) application that failed on a shortage of Graphic handles because of not promptly disposing them. It was generating images.
Dispose 用于处置非托管资源。
因此,根据经验,我将 IDisposable 对象的任何实例化都包装在 using 语句中,因此我不必担心 Pen 拥有哪些非托管资源。
Dispose is used to dispose of unmanaged resources.
So, as a rule of thumb, I wrap any instantiations of IDisposable objects in a using statement, so I don't have to worry about what unmanaged resource a Pen has.