218

就像是:

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

我认为这不是退货声明的合适位置,是吗?

4

7 回答 7

208

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

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

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

一样糟糕

Something y;
using ( var x = new Something() ) {
  y = x;
}
于 2009-03-19T16:02:18.627 回答
165

完全没问题。

你显然在想

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

被一味翻译成:

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

诚然,这将是一个问题,并且会使using声明变得毫无意义——这就是为什么它不是这样做的。

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

于 2009-03-19T16:01:54.370 回答
102

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

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

将计算返回表达式,然后执行 finally 块,然后方法将返回。

于 2009-03-19T15:56:53.227 回答
28

这将完全正常,就像在中间返回一样try{}finally{}

于 2009-03-19T15:55:30.827 回答
19

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

来自MSDN

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

于 2009-03-19T15:56:05.163 回答
17

下面的代码显示了如何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' 被释放。

在 return 语句之后但在函数退出之前调用处置的。

于 2017-08-02T09:35:38.017 回答
-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();
        }
    }
}

我传入了一个要输出为 csv 的 DataTable。在中间返回时,它将所有行写入流,但输出的 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();
}
于 2016-09-23T20:37:50.697 回答