สิ่งที่ต้องการ:
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();
}