我有一个具有一次性物体作为成员的物体。
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
正在析构函数中处理。这会有用吗?这种方法有什么问题吗?
答案 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>
对象,下列之一都是正确的:
该对象已经运行了终结器,在这种情况下,在对象上调用IDisposable
将是最无用的。
该对象不会运行终结器,但其终结器将被安排运行,因此调用该对象上的Dispose
将毫无用处。
该对象仍然会被正在最终确定的对象使用,因此在其上调用Dispose
会很糟糕。
在某些情况下,在终结器中调用Dispose
可能会有用,但大多数情况符合上面列出的情况,这些情况都有一个共同特征:终结器不应调用Dispose
。