什么时候需要Dispose?

发布于 2024-07-29 22:42:45 字数 520 浏览 3 评论 0原文

当你有这样的代码时:

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

风追烟花雨 2024-08-05 22:42:45

是的,您必须处理它们 - 不仅仅是笔和画笔,还有位图和图形。

当它们超出范围时,它们不会被释放,因为变量本身是引用,而不是对象,并且 C# 编译器不知道所有权是否仍然属于这些引用(例如 FillEllipse理论上,可以记住它给出的引用,并在稍后的某个时刻尝试使用它 - 请记住语言编译器没有任何库语义的特殊知识!)。

如果您想指示所有权仅限于该范围,请使用 using 语句:

using (Bitmap bmp = new Bitmap ( 100, 100 ))
using (Graphics g = Graphics.FromImage ( bmp ))
using (Pen p = new Pen ( Color.FromArgb ( 128, Color.Blue ), 1 ))
using (Brush b = new SolidBrush ( Color.FromArgb ( 128, Color.Blue ) ))
{
    g.FillEllipse ( b, 0, 0, 99, 99 );    
    g.FillRegion ( b, pictureBox1.Region );
}

这将使编译器根据需要自动插入对 Dispose 的调用,确保所有对象一旦离开相应的 using 范围(无论是正常情况下,通过诸如 returnbreak 之类的控制传输,还是异常),就会被处置。

如果您有 C++ 背景,C# 中的 using 直接类似于 const std::auto_ptr,只不过它是一种语言构造,并且只能用于局部变量(即不适用于类字段)。

Yes, you have to dispose them - not just pen and brush, but also Bitmap and Graphics.

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:

using (Bitmap bmp = new Bitmap ( 100, 100 ))
using (Graphics g = Graphics.FromImage ( bmp ))
using (Pen p = new Pen ( Color.FromArgb ( 128, Color.Blue ), 1 ))
using (Brush b = new SolidBrush ( Color.FromArgb ( 128, Color.Blue ) ))
{
    g.FillEllipse ( b, 0, 0, 99, 99 );    
    g.FillRegion ( b, pictureBox1.Region );
}

This will make the compiler insert calls to Dispose automatically as needed, ensuring that all objects are disposed once the corresponding using scope is left (whether normally, by control transfer such as return or break, or an exception).

If you come from a C++ background, using in C# is directly analogous to a const 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).

2024-08-05 22:42:45

我知道其他人已经在这里放置了代码示例,但我开始了,所以我会完成:

using (Bitmap bmp = new Bitmap(100, 100))
{
  using (Graphics g = Graphics.FromImage(bmp))
  {
    using (Pen p = new Pen(Color.FromArgb(128, Color.Blue), 1))
    {
      using (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;
      }
    }
  }
}

我总是在代码中使用 using 因为它会自动在您的对象上调用 Dispose() ,即使 using 块中引发了异常。 我在 SharePoint 项目中经常使用它(但那是另一个故事了......)。

I know other people have put code examples here, but I started so I'll finish:

using (Bitmap bmp = new Bitmap(100, 100))
{
  using (Graphics g = Graphics.FromImage(bmp))
  {
    using (Pen p = new Pen(Color.FromArgb(128, Color.Blue), 1))
    {
      using (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;
      }
    }
  }
}

I always use using in my code since it calls Dispose() on your object automatically, even if there is an exception raised in the using block. I use it a lot for SharePoint projects (but that's another story...).

若水微香 2024-08-05 22:42:45

如果正确使用一次性模式,Dispose 并不是绝对必要的——它将在对象完成时调用,因此您不会泄漏资源或任何东西。

但是,在使用完对象后立即调用 Dispose 是一种好习惯,因为一次性对象通常直接控制通常有限的本机资源。 对象通常不会立即完成/收集,因此一旦您不再使用该对象,这些资源就会闲置、浪费。 处置会立即释放这些资源,以便程序的其他部分(或者在某些情况下,其他程序)可以使用它们。

请注意,using 块会在您使用完对象后自动处置该对象,这就是为什么您很少在 using 中看到 Dispose 的原因堵塞。

简短版本:如果对象实现了 IDisposable,并且您的代码创建了它(即:如果它不是像 Pens.Blue 这样的系统对象,或者 Graphics你在OnPaint等中传递),当你完全完成它时,它应该被处置——无论是通过调用Dispose,还是通过调用其他一些方法指定调用 DisposeClose 是常见的),或者通过使用 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 see Dispose within a using block.

Short version: If the object implements IDisposable, and your code created it (ie: if it's not a system object like Pens.Blue, or the Graphics you get passed in OnPaint etc), it should be disposed when you're totally done with it -- whether by calling Dispose, or by calling some other method that's specified to call Dispose (Close is a common one), or by using a using block. You don't have to dispose it, but you almost always should.

风吹过旳痕迹 2024-08-05 22:42:45

C# 不会在事物超出范围后立即“破坏”或处置它们。

这些类很可能会自动释放它们在特殊的Finalizer方法中持有的非托管资源,当它们在运行后的不确定时间进行垃圾收集时,将调用该方法。超出范围。

但依赖它就等于依赖一些你无法控制的事情,而且可能暂时不会发生。

如果该类实现了 IDisposable,最佳实践是您在某处手动调用 Dispose(),或者最好将其包装在 using 块中。 这样您就可以确定:

A. 非托管资源是
肯定会被释放。

B. 非托管资源被释放
尽快。

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 a using block. That way you can be sure that:

A. The unmanaged resources are
definitely being freed.

B. The unmanaged resources are freed
as soon as possible.

撩发小公举 2024-08-05 22:42:45

是的,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.

小…楫夜泊 2024-08-05 22:42:45

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文