因此,在退出using块时,using语句会自动对正在“使用”的对象调用dispose方法,对吧?
但是什么时候有必要/有益?
例如,假设您具有此方法:
public void DoSomething()
{
using (Font font1 = new Font("Arial", 10.0f))
{
// Draw some text here
}
}
因为对象是在方法中创建的,所以这里必须要有using语句吗?当方法退出时,字体对象还是不会被丢弃?
或者在方法退出后,Dispose方法是否在其他时间运行?
例如,如果方法是这样的:
public void DoSomething()
{
Font font1 = new Font("Arial", 10.0f);
// Draw some text here
}
// Is everything disposed or cleared after the method has finished running?
'using'语句在处理非托管对象(例如数据库连接)时最有用。
这样,无论代码块中发生什么,连接都会关闭并被释放。
更多讨论,请参见CodeProject上的这篇文章:http://www.codeproject.com/KB/cs/tinguusingstatement.aspx
没有using
(或手动调用Dispose()
),最终将丢弃对象,只是在确定的时间。也就是说,它可能会在两天后立即发生,或者(在某些情况下)永远不会发生。
对于诸如网络连接之类的事情,您希望在完成连接后关闭它,而不要在任何时候关闭,否则它会闲逛一个套接字。
此外,对于互斥锁,您不希望它们“在任何时候”被释放,否则很可能导致死锁。
此:
public void DoSomething()
{
using (Font font1 = new Font("Arial", 10.0f))
{
// Draw some text here
}
}
直接映射到此:
public void DoSomething()
{
{
Font font1;
try
{
font1 = new Font("Arial", 10.0f);
// Draw some text here
}
finally
{
IDisposable disp = font1 as IDisposable;
if (disp != null) disp.Dispose();
}
}
}
请注意finally块:即使发生异常,该对象也会被处置。还请注意额外的匿名作用域块:这意味着不仅对象被处置,而且也超出范围。
这里的另一重要事项是保证立即处置。它是确定性。如果没有using语句或类似的构造,则该对象将在方法结束时超出范围,然后可以最终被收集。然后,理想情况下将销毁该资源,以便系统可以对其进行回收。但是“最终”可能不会在一段时间内发生,并且“在理想情况下”和“将会”是完全不同的东西。
因此,“最终”并不总是足够好。诸如数据库连接,套接字,信号量/互斥量以及(在这种情况下)GDI资源之类的资源通常受到严格限制,需要立即进行清理。 using语句将确保这种情况发生。
正在使用的构造强制执行确定性处置-即释放资源。在上面的示例中,是的,如果不使用“ using”语句,则将处置该对象,但仅当推荐的一次性模式(即,来自类终结器的资源的[[dispose)(如果适用)时)已针对相关类(在您的示例中为Font类)实现。应该注意的是,using构造只能与实现IDisposable
接口的对象一起使用。该对象上存在该接口,允许使用“调用” Dispose
方法。
最后,using语句“加入” try / finally构造以确保无论所包含的代码引发异常如何都调用Dispose。
当方法退出时,是否会丢弃Font对象?
不,它将变为未引用,因此有资格进行垃圾回收。除非有别的东西(例如保存在另一个数据结构中的引用)保留在引用上。
或者在方法退出后,Dispose方法是否在其他时间运行?
是的,在不分配太多内存的过程中,方法退出后可能要花费相当长的时间。
垃圾回收本质上是异步的和惰性的,因此,如果内存不是太有限,它是确保释放内存的好方法;但几乎没有其他资源。
如果一个类实现了IDisposable,那么几乎在您要创建的任何实例上调用Dispose几乎是您的问题。这是我建议使用的模式,
whenever创建了这样的实例:using (var instanceName = new DisposableClass())
{
// Your code here
}