ถามเรื่องตัวแปรทั่ว ๆ ที่ใช้ใน sub พอใช้เสร็จต้องจัดการอะไรกับตัวแปรนั้นๆ ไหมครับ
ถาม VB.NET และ C#.NET
ตัวแปรทั่ว ๆ ไปที่เราประกาศขึ้นมาใช้ในแต่ละ sub พอใช้ sub นั้นเสร็จแล้วต้องจัดการอะไรกับตัวแปรต่อไหมครับ
อย่างเช่นตัวแปร integer,string,double,sqldatareader,datatable,sqlcommand,sqlconnection อื่น ๆ อีกมากมาย
ปกติแล้วถ้าเราไม่ได้ทำอะไรกับตัวแปรเหล่านี้ ตัวภาษาเองจะสามารถจัดการให้เราอัตโนมัติได้ไหมครับ(ทำลายตัวแปรนั้นไหม) เพราะส่วนใหญ่ตัวแปรอย่างพวก string,integer อะไรพวกนี้เหมือนส่วนใหญ่ไม่ได้ให้ความสำคัญกัน แต่จะให้ความสำคัญกับพวก Datatable,Dataset,Connection อะไรประมาณนี้ครับ ขอคำแนะนำด้วยครับ
ยอดชาย
----------------------------------------
1. ตัวแปรที่เป็น value type เช่น Structure, Integer, Byte, Boolean ฯลฯ
ไม่ต้องทำอะไรทั้งสิ้น เพราะมันจะถูกคืนหน่วยความจำเองเมื่อโค้ดออกจาก scope ที่ประกาศตัวแปรนั้นๆ
เช่น ตัวแปร x As Integer ใน Sub A()
เมื่อ Sub A เริ่มทำงาน เมื่อไหร่ ตัวแปร x จึง "เกิด" กินพื้นที่ 4 ไบต์ใน stack
และเมื่อเจอ End Sub (หรือเมื่อการทำงานออกจาก Sub A) ตัวแปร x ก็จะ "ตาย" และคืนหน่วยความจำ
2. ตัวแปรที่เป็น Reference type เช่น Class, String, Array, Delegate
โดยตัวแปรมันเอง (เรียกว่า object reference) นี่ส่วนหนึ่ง
และเมื่อมีการสร้างอ๊อบเจ็กต์ (object) แล้วเอาตัวแปรเมื่อกี้ไปชี้ นี่ก็อีกส่วนหนึ่ง
Sub Foo()
Dim c As Course ' ---- c เป็น object reference
c = New Course() ' ---- เกิดการสร้าง object ใหม่เกิดขึ้นมา แล้วให้ c ไปชี้
c = Nothing ' ---- ไม่จำเป็น
End Sub
เฉพาะส่วน object reference จะใช้พื้นที่ 4 ไบต์ใน เครื่อง 32-bit
หรือ 8 ไบต์ในเครื่อง 64-bit ก็อยู่ใน stack จะเกิดและตายในทำนองเดียวกับ Value types ทั้งหลาย
ดังนั้น เราจะกำหนดค่าให้ Nothing หรือไม่ ก็ไม่จำเป็นนัก คือมีค่าผลเหมือนๆ กัน
ส่วนที่เป็นเรื่องหน่อย ก็ตรงอ๊อบเจ็กต์ที่สร้างขึ้น (ในหน่วยความจำของโปรแกรม
ส่วนที่เรียกว่า managed heap นั่นแหล่ะครับ)
ตรงนี้ถูกจัดการด้วย Garbage Collector (GC)
ตอบย่อๆ เฉพาะสำหรับกระทู้นี้คือ
ถ้า อ๊อบเจ็กต์นั้นมีเมธอด Dispose หรือ Implements อินเทอร์เฟส IDisposable
ก็ให้เรียกเมธอด Dispose นั้นด้วย
ก่อนที่ตัวแปร reference นั้นจะถูกกำหนดเป็น Nothing หรือ "ตาย" ไปเสียก่อน
เช่น
Sub Foo2()
Dim c As New Course()
...
If (TypeOf c Is IDisposable) Then
DirectCast(c, IDisposable).Dispose()
End If
c = Nothing ' ---- ไม่จำเป็นอยู่ดี
End Sub
ไม่อย่างนั้นแล้ว เดี๋ยว c มันเกิด nothing หรือ ตายไป
เราจะไม่มีโอกาสเปลี่ยนใจมาเรียก Dispose ให้กับ "อ๊อบเจ็กต์" อีกแล้ว
ปล.
เรื่องของ Dispose ให้ค้นหาอ่านได้จากเว็บบอร์ดเกรทเฟรนส์ เพิ่มเติมด้วยจะดีมาก
นอกจากกรณีที่ควร Dispose ถ้ามีให้ Dispose แล้ว
อีกกรณีก็เรื่อง COM object ที่ คุณนายเคยเขียนวิธีการ Release COM object อย่างถูกวิธีไว้
ก็ค้นหาจากเว็บบอร์ดนี้ได้อีกเช่นกัน.
surrealist
----------------------------------------
ขอบคุณมากนะครับที่อุตส่าห์สละเวลามาอธิบายแบบละเอียดเลย
จากที่ผมเข้าใจ คือ
1.class ที่เราสร้างขึ้นมาเองเวลาที่ใช้น่าจะเป็นแบบนี้ใช่ไหมครับ (ตัวอย่างที่อาจารย์ให้ดู)
Sub Foo2()
Dim c As New Course()
...
If (TypeOf c Is IDisposable) Then
DirectCast(c, IDisposable).Dispose()
End If
c = Nothing ' ---- ไม่จำเป็นอยู่ดี
End Sub
2.ส่วนที่ว่า
c = Nothing ' ---- ไม่จำเป็นอยู่ดี หมายถึงไม่มีประโยชน์ที่ใช้คำสั่ง c = Nothing หากทำ Dispose แล้ว
(ความเข้าใจของผมในตอนนี้คือ C คือ Object ที่ Instant มาจาก Class Course ถูกไหมครับ)
3.ตัวแปรพวกนี้ sqldatareader,datatable,sqlcommand,sqlconnection (Reference Type )
ตอนที่จบ sub ถ้าอ๊อบเจ็กต์นั้นมีเมธอด Dispose หรือ Implements อินเทอร์เฟส IDisposable ก็ให้เรียกเมธอด Dispose นั้นด้วย
ขอบคุณมากครับ
ปล.ผมเพิ่งทราบนะครับว่า string เป็นตัวแปรแบบ Reference type แล้วตัวแปรแบบ string ต้องจัดการยังไงเมื่อจบ sub ครับ **
ยอดชาย
---------------------------------------- ตอบ
1. ใช่ครับ แต่เรามีประโยคที่สั้นกว่าในการ dispose คือ Using statement เช่น
Using x As New Class1
' ---- use the x object.
End Using ' --- at End Using, x will be disposed if it implements IDisposable.
2. ต้องเข้าใจให้ชัดเจนก่อนว่า c ไม่ใช่อ๊อบเจ็กต์ แต่เป็น object reference (ตัวpointerชี้ไปยัง object เท่านั้น)
การที่ให้ c เป็น Nothing คือ ตัวชี้ที่เคยชี้ไปยังอ๊อบเจ็กต์ ก็ไม่ชี้แล้ว ส่วนอ๊อบเจ็กต์นั้นยังคงอยู่ครับ
"ไม่มีประโยชน์ที่ใช้คำสั่ง c = Nothing หากทำ Dispose แล้ว"
ไม่ถูกต้องทั้งหมดครับ แต่ก็ไม่ผิด
3. สังเกตง่ายๆ ว่า ถ้า class นั้นๆ มีเมธอด Close ให้เรียก Close เมื่อใช้เสร็จ
ถ้ามีเมธอด Dispose ให้เรียก Dispose เมื่อใช้เสร็จ (หรือใช้ Using statement แทน)
ความแตกต่างระหว่าง Close กับ Dispose ก็มีครับ
แต่ก่อนผมเคยบอกในเว็บบอร์ดว่ามันไม่ต่างกัน ตอนนี้ขอเปลี่ยนข้อมูลใหม่นะครับ
Close - ใช้เรียกเมื่อเราเลิกใช้แล้ว แต่อ๊อบเจ็กต์นั้นยังใช้ซ้ำได้อีก
Dispose - ใช้เรียกเมื่อเราเลิกใช้แล้วจริงๆ อ๊อบเจ็กต์นั้นจะอยู่ในสถานะที่ใช้อีกไม่ได้
ตัวแปร reference นอกเหนือจาก Class เช่น String, Array, Delegate จะอยู่ในการควบคุม
ของ CLR ครับ เราไม่จำเป็นต้องไปจัดการด้วยตนเองเลย จริงๆ แล้ว อาจจะเป็นหน้าที่ของ
คอมไพเลอร์ของภาษาที่เราใช้ เพราะโดย syntax มันก็พยายามทำให้เรามองไม่เห็นอยู่แล้ว
ว่าเป็น reference type เช่น เราไม่จำเป็นต้อง new อ๊อบเจ็กต์ string เอง
surrealist
----------------------------------------
ขอบคุณ อาจารย์ , คุณ ยอดชาย , GF Board ครับ
1 ความคิดเห็น:
ขอบคุณครับ
แสดงความคิดเห็น