C#:IDisposable类需要'using'子句吗?

时间:2011-03-02 02:34:03

标签: c# idisposable using

如果使用IDisposable类,我是否应该始终使用using子句,例如:

using (MyClass myclass = new MyClass())
{
...
}

7 个答案:

答案 0 :(得分:4)

using语句确保调用Dispose以释放资源,即使发生异常或对象超出范围也是如此。

这比使用以下代码块

更简单
try
{
   ...
}
catch()
{
   // Handle exception
}
finally
{
    // Free resources by calling Dispose()
}

注意
如果不想处理catch,则不需要exception块。在这种情况下,try ... finally块就足够了(正如其他答案所指出的那样)。


替代方式
您可以在同一个using语句中创建多个一次性对象的实例,例如

using(MyClass myclass1 = new MyClass(), 
      MyClass myclass2 = new MyClass())
{
    ...
}


实施例
来自Understanding the 'using' statement in C#

using (MyResource myRes = new MyResource())
{
    myRes.DoSomething();
}

被翻译为(CLR

MyResource myRes= new MyResource();
try
{
    myRes.DoSomething();
}
finally
{
    // Check for a null resource.
    if (myRes!= null)
    {
        // Call the object's Dispose method.
        ((IDisposable)myRes).Dispose();
    }
}

您可以查看示例开头指定的链接中生成的MSIL


更多信息

答案 1 :(得分:2)

它使代码更具可读性。因此,作为规则,您应该在using块中声明和实例化对象。它确保即使发生异常也会调用Dispose方法。在编译时,相同的表达式看起来像this

{
  MyClass myclass = new MyClass ();
  try {
    //Do something with myclass
  }
  finally {
    if (myclass != null)
      ((IDisposable)myclass).Dispose();
  }
}

答案 2 :(得分:0)

using子句是以下代码块中的语法糖:

MyClass myclass = null;
try
{
     myclass = new MyClass();
     //do work
}
finally
{
     if(myclass != null)
          myclass.Dispose();
}

如果一个类实现了IDisposable,那么在使用它时应该确保调用Dispose。 using子句只是一种简单的方法。所以你不必使用“使用”来做,但你应该确保它被调用。

答案 3 :(得分:0)

如果某个类实现了IDisposable,那么在完成该对象后,应始终调用Dispose。 C#提供using语句作为语法糖,使这更容易。因此,不需要使用using来呼叫Dispose。也就是说,这是调用Dispose的事实上的标准方式。即如果你的代码没有使用using而是在finally块中调用Dispose,那么对于有经验的编码人员来说,这看起来有点奇怪。

使用块的扩展(假设MyClass是引用类型)是:

{
    MyClass myclass = new MyClass();
    try {
        //...
    }
    finally {
        if (myclass != null) ((IDisposable)myclass).Dispose();
    }
}

using版本更易于编码且更易于阅读。

答案 4 :(得分:0)

简单地说,如果它实现了IDisposable,并且你想要调用该方法(当你在做的时候也在finally块中的例外。使用。

GC不会为您调用Dispose()!有些类实现了终结器~ClassName()但是尽量避免这种情况,因为它有很多副作用并且不明显。

您可以将using语句读作:

TestClass test = new TestClass();
try
{
      test.DoSomething();
}
finally
{
      test.Dispose();
}

答案 5 :(得分:0)

只要对象的生命周期足够短以至于可以实现,就应该始终这样做。有时您必须单独处理清理,因为您拥有长寿命的对象,这些对象在代码块完成后会持续很长时间。

答案 6 :(得分:0)

创建IDisposable对象时有三种情况:

  1. 该对象将需要一段时间,但在当前代码块退出后将不再需要。
  2. 该对象将被赋予当前例程的调用者,然后由它负责。
  3. 负责IDisposable对象的类将它存储在一个字段中,以便在将来的方法/属性调用中使用它。

在场景#1中,使用“using”块来创建对象;它的清理工作将自动处理。

在场景#2中,使用带有“ok”变量的“try-finally”块,该变量最初设置为“False”,但在“try”结束时或在任何返回之前设置为“True”;在finally中,如果“oK”为false,则调用Dispose以确保部分构造的对象被清除。

在场景#3中,一旦创建了对象,就将其存储在字段中,并定义一个IDisposable.Dispose方法,该方法将字段中的值复制到变量中,将该字段归零,如果变量为非变量-null,Dispose it(如果有多个线程同时调用Dispose的可能性,请使用Interlocked.Exchange来锁定并清除该字段)。构造函数也应该像场景#2中的函数一样受到保护。