[C#] using 블록의 중간에 반환

다음과 같은 것 :

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

나는 그것이 반품 진술에 대한 적절한 장소가 아니라고 생각합니까?



답변

다른 사람들이 일반적으로 지적했듯이 이것은 문제가되지 않습니다.

using 문 중간에 반환하고 추가로 in using 변수를 반환하면 문제가 발생할 수 있습니다. 그러나 다시 말하지만, 반환하지 않고 단순히 변수에 대한 참조를 유지하더라도 문제가 발생할 수 있습니다.

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

나쁘게

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


답변

완벽하게 괜찮습니다.

당신은 분명히 생각

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

맹목적으로 번역 :

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

어느 쪽이 문제가 될 수 있으며, 그 using진술을 무의미 하게 만들 것입니다 . — 그것이 그렇게하지 않는 이유입니다 .

컴파일러는 블록을 떠나는 방법에 관계없이 컨트롤이 블록을 떠나기 전에 객체가 배치되도록합니다.


답변

전혀 문제 없습니다. 왜 이것이 잘못되었다고 생각하십니까?

using 문은 try / finally 블록에 대한 구문 설탕이며 Grzenio는 try 블록에서 돌아 오는 것이 좋습니다.

리턴 표현식이 평가되고 finally 블록이 실행 된 후 메소드가 리턴됩니다.


답변

중간에 돌아 오는 것처럼 완벽하게 작동합니다. try{}finally{}


답변

그것은 완전히 허용됩니다. 사용하여 문으로 IDisposable 개체에 상관없이 배치되지 않습니다 보장합니다.

에서 MSDN :

using 문을 사용하면 객체에서 메서드를 호출하는 동안 예외가 발생하더라도 Dispose가 호출됩니다. try 블록 안에 객체를 넣은 다음 finally 블록에서 Dispose를 호출하여 동일한 결과를 얻을 수 있습니다. 실제로 이것은 using 문이 컴파일러에 의해 번역되는 방식입니다.


답변

다음 코드 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 문 다음에 그러나 함수가 종료되기 전에 호출됩니다.


답변

아마도 이것이 허용되는 것은 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();
}