当一个对象只在using语句的范围内创建和使用时,是否在处理其封闭的IDisposable
实例时将其处理掉?如果没有,为什么不呢?
例如,当使用Dapper时,我经常在SqlConnection
的范围内创建一个匿名对象,并给人一种印象,即它会被更快地处理掉 - 但是我最近读到了相反的东西。
using (var connection = new SqlConnection("Connection String"))
{
var parameters = new
{
Message = "Hello world!"
};
connection.Execute("INSERT INTO...", parameters);
}
答案 0 :(得分:3)
您的using
声明基本上等同于:
var connection = new SqlConnection("Connection String");
try
{
var parameters = new
{
Message = "Hello world!"
};
}
finally
{
if (connection != null)
{
((IDisposable)connection).Dispose();
}
}
如您所见,没有理由为您自动处理在IDisposable
块内创建的任何其他try
实例。如果确实需要确保处理其他对象,那么只需嵌套using
语句:
using (var connection = new SqlConnection("Connection String"))
{
using (var otherDisposableObject = new ....)
{
} //otherDisposableObject disposed
} //connection disposed
如果过多的嵌套妨碍了可读性,那么你可以简单地编写using语句,如下所示:
using (var connection = new SqlConnection("Connection String"))
using (var otherDisposableObject = new ....)
using (var anotherDisposableObject = new ....)
using (var andAnotherDisposableObject = new ....)
{
} //andAnotherDisposableObject, anotherDisposableObject, otherDisposableObject and connection all disposed
请记住,您似乎将垃圾收集与处理对象混合在一起。在您的示例中,一旦执行退出parameters
语句,using
就可以实现垃圾收集,因为它没有实时的反馈。
当被垃圾收集到GC
时,它可能永远不会,这取决于你的应用程序的内存压力。 如果是垃圾收集,那么它将被标记为有效以进行最终确定,并且该对象的终结器将被安排运行。同样,如果发生这种情况完全取决于GC
。
最后,如果正确实现了对象的IDisposable
模式并且运行了终结器,则将调用Dispose()
(将成为精确,Dispose(false)
将被调用),对象将处置它可能持有的任何非托管资源(托管资源不能在这种情况下安全地处理,但它确实无关紧要,GC
最终会照顾他们。)
请参阅IDisposable Pattern了解有关其运作方式的更多详情,请查看此优秀的SO answer。