สิ่งที่ต้องการ:
using (IDisposable disposable = GetSomeDisposable())
{
    //.....
    //......
    return Stg();
}
ฉันเชื่อว่ามันไม่ใช่สถานที่ที่เหมาะสมสำหรับการส่งคืนสินค้าใช่หรือไม่
สิ่งที่ต้องการ:
using (IDisposable disposable = GetSomeDisposable())
{
    //.....
    //......
    return Stg();
}
ฉันเชื่อว่ามันไม่ใช่สถานที่ที่เหมาะสมสำหรับการส่งคืนสินค้าใช่หรือไม่
คำตอบ:
ตามที่คนอื่นหลายคนชี้ให้เห็นโดยทั่วไปแล้วนี่ไม่ใช่ปัญหา
กรณีเดียวที่จะทำให้คุณมีปัญหาคือถ้าคุณกลับมาที่ตรงกลางของคำสั่งการใช้และส่งกลับในการใช้ตัวแปร แต่จากนั้นอีกครั้งสิ่งนี้จะทำให้คุณมีปัญหาแม้ว่าคุณจะไม่ได้กลับมาและเพียงแค่อ้างอิงถึงตัวแปร
using ( var x = new Something() ) { 
  // not a good idea
  return x;
}
เช่นเดียวกับที่ไม่ดี
Something y;
using ( var x = new Something() ) {
  y = x;
}
              returnคำสั่งทำให้จุดสิ้นสุดของusingบล็อกไม่สามารถเข้าถึงได้โดยเส้นทางรหัสใด ๆ จุดสิ้นสุดของusingบล็อกต้องถูกเรียกใช้เพื่อให้สามารถกำจัดวัตถุได้หากจำเป็น
                    มันดีมาก
เห็นได้ชัดว่าคุณกำลังคิดว่า
using (IDisposable disposable = GetSomeDisposable())
{
    //.....
    //......
    return Stg();
}
แปลแบบสุ่มสี่สุ่มห้าเป็น:
IDisposable disposable = GetSomeDisposable()
//.....
//......
return Stg();
disposable.Dispose();
ซึ่งเป็นที่ยอมรับจะมีปัญหาและจะทำให้usingคำสั่งค่อนข้างไม่มีจุดหมาย --- ซึ่งเป็นสาเหตุที่ไม่ใช่สิ่งที่มันทำ  
คอมไพเลอร์ตรวจสอบให้แน่ใจว่าวัตถุถูกกำจัดก่อนการควบคุมออกจากบล็อก - ไม่ว่ามันจะออกจากบล็อกอย่างไร
ไม่เป็นปัญหาเลย ทำไมคุณถึงเชื่อว่ามันผิด
การใช้ข้อความเป็นเพียงน้ำตาลเชิงประโยคสำหรับการลอง / สุดท้ายบล็อกและในขณะที่ Grzenio บอกว่ามันดีที่จะกลับมาจากการลองอีกด้วย
นิพจน์ส่งคืนจะถูกประเมินจากนั้นบล็อกสุดท้ายจะถูกดำเนินการจากนั้นวิธีจะส่งคืน
สิ่งนี้จะทำงานได้อย่างสมบูรณ์แบบเช่นเดียวกับการกลับมาอยู่ตรงกลาง try{}finally{}
นั่นเป็นที่ยอมรับโดยสิ้นเชิง ใช้คำสั่งเพื่อให้แน่ใจวัตถุ IDisposable จะถูกกำจัดไม่ว่าสิ่งที่
จากMSDN :
คำสั่งการใช้ทำให้แน่ใจว่าการกำจัดถูกเรียกแม้ว่าข้อยกเว้นจะเกิดขึ้นในขณะที่คุณกำลังเรียกวิธีการบนวัตถุ คุณสามารถบรรลุผลลัพธ์เดียวกันได้โดยวางวัตถุไว้ในบล็อกลองแล้วเรียกใช้ทิ้งในบล็อกสุดท้าย ในความเป็นจริงนี่คือวิธีการแปลคำสั่งการใช้โดยคอมไพเลอร์
รหัสตะโกนแสดงวิธีการ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' ถูกกำจัด
การจำหน่ายจะถูกเรียกหลังจากคำสั่งส่งคืน แต่ก่อนที่จะออกจากฟังก์ชั่น
บางทีมันอาจจะไม่จริง 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();
}