在使用块的中间返回

时间:2009-03-19 15:53:40

标签: c# dispose idisposable using-statement

类似的东西:

using (IDisposable disposable = GetSomeDisposable())
{
    //.....
    //......
    return Stg();
}

我认为这不是一个适当的回复声明的地方,是吗?

7 个答案:

答案 0 :(得分:179)

正如其他几位人士所指出的那样,这不是一个问题。

它会导致问题的唯一情况是,如果您在using语句的中间返回并另外返回in using变量。但话说回来,即使你没有返回并只是保留对变量的引用,这也会导致问题。

using ( var x = new Something() ) { 
  // not a good idea
  return x;
}

同样糟糕

Something y;
using ( var x = new Something() ) {
  y = x;
}

答案 1 :(得分:118)

完全没问题。

你显然在想

using (IDisposable disposable = GetSomeDisposable())
{
    //.....
    //......
    return Stg();
}

被盲目翻译成:

IDisposable disposable = GetSomeDisposable()
//.....
//......
return Stg();
disposable.Dispose();

不可否认,这将是一个问题,并且会使using声明变得毫无意义 - 这就是为什么它的作用。

编译器确保在控件离开块之前放置对象 - 无论它如何离开块。

答案 2 :(得分:91)

这绝对没问题 - 完全没问题。为什么你认为这是错的?

using语句只是try / finally块的语法糖,正如Grzenio所说,从try块返回也没问题。

将评估返回表达式,然后执行finally块,然后该方法将返回。

答案 3 :(得分:25)

这将完美地运行,就像在try{}finally{}

中间返回一样

答案 4 :(得分:16)

这完全可以接受。 using 语句可确保IDisposable对象无论如何都会被处理。

来自MSDN

  

using语句确保即使在对象上调用方法时发生异常,也会调用Dispose。您可以通过将对象放在try块中然后在finally块中调用Dispose来实现相同的结果;实际上,这就是编译器如何翻译using语句。

答案 5 :(得分:9)

下面的代码显示了using的工作原理:

private class TestClass : IDisposable
{
   private readonly string id;

   public TestClass(string id)
   {
      Console.WriteLine("'{0}' is created.", id);
      this.id = id;
   }

   public void Dispose()
   {
      Console.WriteLine("'{0}' is disposed.", id);
   }

   public override string ToString()
   {
      return id;
   }
}

private static TestClass TestUsingClose()
{
   using (var t1 = new TestClass("t1"))
   {
      using (var t2 = new TestClass("t2"))
      {
         using (var t3 = new TestClass("t3"))
         {
            return new TestClass(String.Format("Created from {0}, {1}, {2}", t1, t2, t3));
         }
      }
   }
}

[TestMethod]
public void Test()
{
   Assert.AreEqual("Created from t1, t2, t3", TestUsingClose().ToString());
}

输出:

  

' T1'创建。
  ' T2'创建。
  ' T3'创建。
  '从t1,t2,t3'创建创建。
  ' T3'处置   ' T2'处置   ' T1'处置。

在返回语句之后但在函数退出之前调用dispos。

答案 6 :(得分:-4)

或许100%无误,这是可以接受的......

如果您正好使用嵌套并从嵌套的嵌套中返回,则可能不安全。

以此为例:

using (var memoryStream = new MemoryStream())
{
    using (var textwriter = new StreamWriter(memoryStream))
    {
        using (var csv = new CsvWriter(textwriter))
        {
            //..write some stuff to the stream using the CsvWriter
            return memoryStream.ToArray();
        }
    }
}

我传入一个DataTable作为csv输出。在中间返回时,它将所有行写入流,但输出的csv总是缺少一行(或多个,取决于缓冲区的大小)。这告诉我,某些事情没有得到妥善关闭。

正确的方法是确保所有以前的使用都妥善处理:

using (var memoryStream = new MemoryStream())
{
    using (var textwriter = new StreamWriter(memoryStream))
    {
        using (var csv = new CsvWriter(textwriter))
        {
            //..write some stuff to the stream using the CsvWriter
        }
    }

    return memoryStream.ToArray();
}