喜欢的东西:

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

我想这里不适合做退货声明,对吧?


这将工作得非常好,就像在try{}finally{}中间返回一样


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

从MSDN:

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


绝对没问题,一点问题都没有。你为什么认为这是错的?

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

返回表达式将被求值,然后finally块将被执行,然后该方法将返回。


完全没问题。

你显然是这么想的

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

被盲目地翻译成:

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

不可否认,这将是一个问题,并将使using语句变得毫无意义——这就是为什么它不是这样做的。

编译器确保对象在控件离开块之前被释放——不管它如何离开块。


正如其他几个人指出的那样,一般来说,这不是一个问题。

唯一会给你带来问题的情况是,如果你在using语句中间返回,并额外返回in using变量。但是,即使您不返回,而只是保留对变量的引用,这也会导致问题。

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

同样糟糕

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

也许这并不是百分百可以接受的……

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

举个例子:

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();
        }
    }
}

我正在传递一个数据表,以输出为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();
}

下面的代码显示了如何使用:

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'被创建。 'Created from t1, t2, t3'被创建。 't3'被销毁。 't2'被释放。 't1'被丢弃。

在return语句之后,函数退出之前调用dispose函数。