5

例如我有一个方法

SomeMethod(Graphics g)
{
    ...
}

如果我以某种方式调用此方法

SomeMethod(new Graphics())

我的图形对象会自动处理还是应该g.Dispose() 在方法结束时手动调用?

SomeMethod(Graphics g)
{
    ...
    g.Dispose();
}
4

5 回答 5

7

一次性对象不会被自动处理(它们最接近的方法是实现一个Dispose在必要时调用的终结器)。您必须通过调用Dispose()或将其与using块一起使用来手动执行此操作。

如果你想自动处理对象,你可以这样做:

using (var g = new Graphics()) {
    SomeMethod(g);
}

using 块确保Dispose()在块结束后立即自动调用该方法(因此在这种情况下,afterSomeMethod返回或抛出异常)。

注意:如果可能,您应该将对象放置在您创建它的位置附近。接收一个有效的对象并在方法中处理它可能会导致混淆。

Dispose()当调用终结器时,图形和可能大多数(如果不是全部)实现此接口的 BCL 类也将调用。这是正确实施的一部分IDisposable。但是,您永远不知道何时调用终结器,如果您需要确定性地处理您的对象,则不应依赖此实现细节。

于 2012-04-11T07:39:42.317 回答
4

使用一次性物品的正确方法是将它们包装在using块中:

using (var g = new Graphics()) {
  SomeMethod(g);
}

当执行离开using块时,Graphics即使抛出异常,也会正确处理。

但是,如果您不使用using块显式或隐式处理对象,则在垃圾收集时对象仍将被处理(假设终结器正确调用了Dispose它应该的)。当这种情况发生时不在您的控制范围内,这就是为什么您应该确保在不再需要一次性对象以释放对象占用的资源时立即正确处置它们。

于 2012-04-11T07:50:51.480 回答
3

您可能应该使用 using 语句

using (var graphicsObject = new Graphics()) {
    SomeMethod(graphicsObject);
}

即使发生异常,该对象也会在 using 语句的末尾自动释放。

于 2012-04-11T07:41:12.080 回答
2

检查图形类

public sealed class Graphics : MarshalByRefObject, 
    IDeviceContext, IDisposable

它实现了IDisposable接口,因此如果您将using语句与 Graphics 对象一起使用,那么它将自动释放。

在你的例子中

SomeMethod(Graphics g)
        {
        ...
        g.Dispose();
        }

它将使用g.Dispose, 但最佳做法是using声明。

例子:

using (Graphics g = this.CreateGraphics())
{
//Do some graphics operation.
}
于 2012-04-11T07:47:30.257 回答
2

在您的示例中,您不应该处理作为参数提供给您的对象。这是不可取的,因为该对象可以在您的方法之外使用。实用程序对象的处置应该(通常)以您创建它的相同方法进行。类范围对象或状态对象的例外。

与其他答案一样,用于using创建和处置对象。这仅在使用一些有价值的资源(如数据库连接)的对象上才是真正需要的。话虽如此,如果对象实现它,您应该始终调用Dispose()(显式或通过using),因为这意味着它使用非托管或大量资源。

您不调用Dispose(无论哪种方式)的所有 .NET Framework 对象最终都将由垃圾收集器自动处理。接口的正确实现IDisposable应该具有调用Dispose. 这是为了确保有价值的资源不会因为糟糕的代码而丢失。你的资源会在很久以后才被释放,但它们会,这很重要。这就是 .NET 中所有一次性类的实现方式以及所有类应该如何实现的方式IDisposable

您的代码应如下所示:

using(Graphics g = new Graphics())
{
    SomeMethod(g)
    {
        ...
    }
}

检查Microsoft 对IDisposable.Dispose方法的建议。

于 2012-04-11T09:10:55.343 回答