仅在using语句的范围内创建和使用时的对象生存期

时间:2015-11-25 10:12:53

标签: c# dapper

当一个对象只在using语句的范围内创建和使用时,是否在处理其封闭的IDisposable实例时将其处理掉?如果没有,为什么不呢?

例如,当使用Dapper时,我经常在SqlConnection的范围内创建一个匿名对象,并给人一种印象,即它会被更快地处理掉 - 但是我最近读到了相反的东西。

using (var connection = new SqlConnection("Connection String"))
{
    var parameters = new
    { 
        Message = "Hello world!"
    };

    connection.Execute("INSERT INTO...", parameters);
}

1 个答案:

答案 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