即使没有引用它的变量,“使用{}”良好实践来处置对象

时间:2014-02-20 21:40:36

标签: c# idisposable using

在我的公司,我看到这样的代码

using (LoggerFactory.GetTracer(_log.ModuleName + "._GetAccessTokenFromWns"))
{...}

当我抬起头时,我学会了它处理由“使用”括号内声明的变量引用的对象。

对于上面的代码,它是否也有帮助,那里没有引用工厂返回的对象的变量?

谢谢,

4 个答案:

答案 0 :(得分:4)

在看到你的问题后,我写了一个简单的代码:

using (new FileStream("sample.txt",FileMode.CreateNew))
{

}

然后我看一下制作的IL code

    .method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // Code size       35 (0x23)
  .maxstack  2
  .locals init ([0] class [mscorlib]System.IO.FileStream CS$3$0000,
           [1] bool CS$4$0001)
  IL_0000:  nop
  IL_0001:  ldstr      "asdas.txt"
  IL_0006:  ldc.i4.1
  IL_0007:  newobj     instance void [mscorlib]System.IO.FileStream::.ctor(string,
                                                                           valuetype [mscorlib]System.IO.FileMode)
  IL_000c:  stloc.0
  .try
  {
    IL_000d:  nop
    IL_000e:  nop
    IL_000f:  leave.s    IL_0021
  }  // end .try
  finally
  {
    IL_0011:  ldloc.0
    IL_0012:  ldnull
    IL_0013:  ceq
    IL_0015:  stloc.1
    IL_0016:  ldloc.1
    IL_0017:  brtrue.s   IL_0020
    IL_0019:  ldloc.0
    IL_001a:  callvirt   instance void [mscorlib]System.IDisposable::Dispose()
    IL_001f:  nop
    IL_0020:  endfinally
  }  // end handler
  IL_0021:  nop
  IL_0022:  ret
} // end of method Program::Main

正如您所看到它仍在调用Dispose方法。它会在FileStream阻止之前创建try实例,然后在Dispose中调用finally方法我认为这是using语句的另一个优点。

答案 1 :(得分:3)

对象的“处置”涉及清理它可能已初始化以供自己使用的任何资源。重要的任务不是清理引用,而是清除文件锁,互斥锁等。

答案 2 :(得分:3)

这是确保处理对象而不为其引入变量的唯一方法。这与

相同
var __invisible = LoggerFactory.GetTracer(_log.ModuleName + "._GetAccessTokenFromWns");
try {
} finally {
    __invisible.Dispose();
}

但没有__invisible变量。

需要变量时,这种结构特别有用,因为熟悉这个习语的读者会发现这样的代码更具可读性。

答案 3 :(得分:2)

我相信它仍然具有同样的效果。如果GetTracer正在返回实现IDisposable的类的实例,那么此代码将确保正确处理该实例。仅仅因为没有返回值的分配并不意味着没有分配需要处置的资源。例如,跟踪器可能正在打开一个文件而没有using语句,即文件锁/ streamreader或者我不知道的任何资源。