在析构函数中处置对象

时间:2010-03-01 17:51:23

标签: c# dispose idisposable

我有一个具有一次性物体作为成员的物体。

public class MyClass
{
    private MyDisposableMember member;

    public DoSomething
    {
         using (member = new MyDisposableMember())
         {
             // Blah...
         }
    }
}

MyClass中有许多方法,都需要using语句。但是,如果我这样做呢?

public class MyClass
{
    private MyDisposableMember member = new MyDisposableMember();

    public DoSomething
    {
         // Do things with member :)
    }

    ~MyClass()
    {
        member.Dispose();
    }
}

如您所见,member正在析构函数中处理。这会有用吗?这种方法有什么问题吗?

7 个答案:

答案 0 :(得分:10)

理想情况下,Dispose()应该在完成之前调用。最好遵循典型的dispose模式,并允许用户正确地Dispose()对象,如果还没有调用,则让终结器处理它

在这种情况下,由于您正在封装IDisposable,因此您根本不需要实现终结器。 (在最终确定时,您的封装成员将最终确定,因此无需最终确定您的对象 - 它只会增加开销。)有关详细信息,请阅读此blog article I wrote封装IDisposable。

答案 1 :(得分:7)

您应该MyClass实施IDisposable。在Dispose()方法内,请致电member.Dispose();。这样程序员就可以控制成员何时被处置。

答案 2 :(得分:3)

不要那样做!

GC将为您执行此操作(间接作为处置对象或另一个将包含析构函数)

MyDisposableMember甚至可能在你处理之前由GC处理 - 那么可能不会是你打算做什么。

更糟糕的是:在处理对象时,向类中添加析构函数(或终结器)会花费额外的时间(因为对象将保留在内存中以用于至少一个集合cyclus,甚至可能提升到下一代)

因此,它将完全没用,甚至适得其反。

答案 3 :(得分:1)

在你的第一个例子中,成员实际上并不是对象状态的一部分,因为你每次使用它时都要实例化它并在之后立即处理它。由于它不是状态的一部分,所以不要对它进行建模,只需在需要时使用局部变量。

更一般地说,你应该将所有处理逻辑放在Dispose()中并实现IDisposable然后使用你的类和using或try-finally

答案 4 :(得分:0)

我唯一看错了(并且它不是错误)的事实是,在using语句中,您在该时间点(当调用您的函数/方法时)显式处理该对象。无法调用析构函数,它们会自动调用。所以在这一点上,成员可能需要一些时间才能被处置掉。最好为MyClass实现IDisposeable接口。

答案 5 :(得分:0)

遵循Microsoft模式是您最好的选择,因此您班级的用户可以完全控制何时处置。

public class MyClass : IDisposable
{
    private MyDisposableMember member = new MyDisposableMember();

    public DoSomething
    {
         // Do things with member :)
    }

    ~MyClass()
    {
        Dispose(false);
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (disposing)  // Release managed resources
        {           
            member.Dispose();
        }

        // Release unmanaged resources
    }
}

答案 6 :(得分:0)

当终结器运行时,对于它拥有引用的几乎任何 <Form method="post" action="www.TestAddress.com/TestPage.php"> <input Type="Text" name="TestName" value="SomeValue" /> <input Type="Submit" value="Submit" /> </Form> 对象,下列之一都是正确的:

  1. 该对象已经运行了终结器,在这种情况下,在对象上调用IDisposable将是最无用的。

  2. 该对象不会运行终结器,但其终结器将被安排运行,因此调用该对象上的Dispose将毫无用处。

  3. 该对象仍然会被正在最终确定的对象使用,因此在其上调用Dispose会很糟糕。

  4. 在某些情况下,在终结器中调用Dispose可能会有用,但大多数情况符合上面列出的情况,这些情况都有一个共同特征:终结器不应调用Dispose