C# 在 using 块中间返回

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/662773/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 12:22:25  来源:igfitidea点击:

returning in the middle of a using block

c#disposeidisposableusing-statement

提问by tafa

Something like:

就像是:

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

I believe it is not a proper place for a return statement, is it?

我相信这不是 return 语句的合适位置,是吗?

采纳答案by JaredPar

As several others have pointed out in general this is not a problem.

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

The only case it will cause you issues is if you return in the middle of a using statement and additionally return the in using variable. But then again, this would also cause you issues even if you didn't return and simply kept a reference to a variable.

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

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

Just as bad

一样糟糕

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

回答by Grzenio

This will work perfectly fine, just as returning in the middle of try{}finally{}

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

回答by mbillard

That is totally acceptable. A usingstatement ensures the IDisposable object will be disposed no matter what.

这是完全可以接受的。一个使用语句确保了IDisposable对象将被无论什么配置。

From MSDN:

MSDN

The using statement ensures that Dispose is called even if an exception occurs while you are calling methods on the object. You can achieve the same result by putting the object inside a try block and then calling Dispose in a finally block; in fact, this is how the using statement is translated by the compiler.

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

回答by Jon Skeet

It's absolutely fine - no problem at all. Why do you believe it's wrong?

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

A using statement is just syntactic sugar for a try/finally block, and as Grzenio says it's fine to return from a try block too.

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

The return expression will be evaluated, then the finally block will be executed, then the method will return.

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

回答by James Curran

It's perfectly fine.

完全没问题。

You are apparently thinking that

你显然在想

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

is blindly translated into:

被盲目翻译成:

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

Which, admittedly, would be a problem, and would make the usingstatement rather pointless --- which is why that's notwhat it does.

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

The compiler makes sure that the object is disposed before control leaves the block -- regardless of how it leaves the block.

编译器确保在控制离开块之前处理对象——不管它如何离开块。

回答by yeahright

Perhaps it isn't 100% true that this is acceptable...

也许这不是 100% 正确的,这是可以接受的......

If you happen to be nesting usings and returning from within a nested one, it might not be safe.

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

Take this as an example:

以此为例:

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

I was passing in a DataTable to be outputted as csv. With the return in the middle, it was writing all the rows to the stream, but the outputted csv was always missing a row (or multiple, depending on the size of the buffer). This told me that something wasn't being closed properly.

我正在传入一个要作为 csv 输出的数据表。在中间返回时,它将所有行写入流,但输出的 csv 总是缺少一行(或多个,取决于缓冲区的大小)。这告诉我有些东西没有正确关闭。

The correct way is to make sure all the previous usings are disposed properly:

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

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

回答by Bertrand

The code bellow shows how usingis working:

下面的代码显示了如何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());
}

Output:

输出:

't1' is created.
't2' is created.
't3' is created.
'Created from t1, t2, t3' is created.
't3' is disposed.
't2' is disposed.
't1' is disposed.

't1' 已创建。
't2' 已创建。
't3' 已创建。
'Created from t1, t2, t3' 被创建。
't3' 已处理。
't2' 已处理。
't1' 已处理。

The disposed are called after the return statement but before the exit of the function.

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