มีวิธีการหรือวิธีอื่นที่มีน้ำหนักเบาในการตรวจสอบว่ามีการอ้างอิงถึงวัตถุที่กำจัดทิ้งหรือไม่?
PS - นี่เป็นเพียงความอยากรู้อยากเห็น (หลับให้สบายไม่ใช่รหัสการผลิต) ใช่ฉันรู้ว่าฉันสามารถจับได้ObjectDisposedException
เมื่อพยายามเข้าถึงสมาชิกของวัตถุ
มีวิธีการหรือวิธีอื่นที่มีน้ำหนักเบาในการตรวจสอบว่ามีการอ้างอิงถึงวัตถุที่กำจัดทิ้งหรือไม่?
PS - นี่เป็นเพียงความอยากรู้อยากเห็น (หลับให้สบายไม่ใช่รหัสการผลิต) ใช่ฉันรู้ว่าฉันสามารถจับได้ObjectDisposedException
เมื่อพยายามเข้าถึงสมาชิกของวัตถุ
Dispose
วิธีนี้สั่งให้วัตถุปล่อยทรัพยากรใด ๆ และทั้งหมดที่ได้มา แต่ยังไม่ได้รับการปลดปล่อย ถ้าออบเจ็กต์ไม่เคยเก็บทรัพยากรDispose
โดยทั่วไปวิธีการของมันจะไม่ต้องทำอะไรเลย หากประเภทประกาศvoid IDisposable.Dispose() {};
ก็สามารถละเว้นIDisposable
โดยไม่มีค่าใช้จ่ายต่ออินสแตนซ์ IsDisposed
ทรัพย์สินซึ่งคาดว่าจะเป็นความจริงใด ๆ ต่อไปนี้โทรจะเลี่ยงการเพิ่มสถานะบูลีนมิฉะนั้นไม่จำเป็นตัวอย่างของหลายชนิดที่อาจจะไม่สนใจทุกDispose
Dispose
IDisposable
คุณจะตรวจสอบได้อย่างไรว่าถูกกำจัดก่อนหรือไม่? แทนที่จะคิดว่ามันไม่ใช่และจับข้อยกเว้น? หรืออย่างใดคุณตั้งใจที่จะจัดการอายุการใช้งานเพื่อที่คุณจะได้รู้ว่ามันถูกกำจัดหรือไม่?
IsDisposed
ธงอาจช่วยป้องกันรหัสจากการสูญเสียเวลาในการดำเนินงานที่ไม่อาจประสบความสำเร็จ แต่ยังคงต้องจัดการกับข้อยกเว้นในกรณีที่วัตถุได้รับการกำจัดระหว่างIsDisposed
การตรวจสอบและความพยายามที่จะใช้มัน
WeakReference
ดูเหมือนจะเกี่ยวข้องที่นี่ ไม่ใช่เครื่องตรวจจับ IDipose'd อย่างแน่นอน แต่มันบอกคุณได้ว่าเป็น GC หรือไม่
คำตอบ:
ไม่ - ไม่รองรับการใช้งานรูปแบบ IDisposable เริ่มต้น
System.Windows.Forms.Control
มียอดIsDisposed
สถานที่ให้บริการซึ่งเป็นที่ตั้งหลังจากที่จริงDispose()
จะเรียกว่า ในอ็อบเจ็กต์ IDisposable ของคุณเองคุณสามารถสร้างคุณสมบัติที่คล้ายกันได้อย่างง่ายดาย
ไม่มีสิ่งใดในตัวที่จะยอมให้สิ่งนี้ คุณจะต้องแสดงคุณสมบัติบูลีน IsDisposed ที่สะท้อนแฟล็กที่กำจัดภายใน
public class SimpleCleanup : IDisposable
{
private bool disposed = false;
public bool IsDisposed
{
get
{
return disposed;
}
}
public SimpleCleanup()
{
this.handle = /*...*/;
}
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
// free only managed resources here
}
// free unmanaged resources here
disposed = true;
}
}
public void Dispose()
{
Dispose(true);
}
}
IDisposablePlus
หรืออะไรก็ได้) ที่สืบทอดมาจากIDisposable
และรวมbool IsDisposed { get; }
ไว้ด้วย ซึ่งทำให้มันเป็นเรื่องง่ายที่จะได้รู้ว่าที่ที่คุณสนับสนุนวัตถุIDisposable
IsDisposed
ถ้าไม่ใช่คลาสของคุณและไม่มีคุณสมบัติ IsDisposed (หรืออะไรที่คล้ายกัน - ชื่อนี้เป็นเพียงแบบแผน) คุณก็ไม่มีทางรู้ได้
แต่ถ้าเป็นชั้นเรียนของคุณและคุณกำลังติดตามการนำไปใช้งานตามมาตรฐานที่กำหนดได้ก็เพียงแค่แสดงฟิลด์ _disposed หรือ _isDisposed เป็นคุณสมบัติและตรวจสอบสิ่งนั้น
Dispose
วิธีการที่จำเป็นในการดำเนินการทำความสะอาดสิ่งที่จะต้องก่อนที่วัตถุถูกยกเลิก; หากไม่จำเป็นต้องล้างข้อมูลก็ไม่จำเป็นต้องทำอะไร การกำหนดให้ออบเจ็กต์ติดตามว่าวัตถุนั้นถูกกำจัดไปแล้วหรือไม่แม้ว่าDispose
เมธอดจะไม่ทำอะไรเลยก็ตามจะต้องใช้IDisposable
อ็อบเจ็กต์จำนวนมากเพื่อเพิ่มแฟล็กเพื่อประโยชน์ที่ จำกัด มาก
อาจมีประโยชน์หากIDisposable
มีคุณสมบัติสองอย่าง - คุณสมบัติหนึ่งที่ระบุว่าวัตถุจำเป็นต้องกำจัดหรือไม่และหนึ่งในนั้นระบุว่าวัตถุไม่ได้ถูกทำให้ไร้ประโยชน์จากการกำจัด Dispose
สำหรับวัตถุที่กำจัดไม่จริงสิ่งที่ทั้งสองค่าจะเป็นจริงในตอนแรกและจะกลายเป็นเท็จหลัง สำหรับวัตถุที่การกำจัดไม่จำเป็นต้องทำการล้างข้อมูลใด ๆ วิธีแรกอาจส่งคืนเท็จเสมอและวิธีที่สองเป็นจริงเสมอโดยไม่ต้องเก็บแฟล็กไว้ที่ใดก็ได้ ฉันไม่คิดว่าจะมีวิธีใดที่สามารถเพิ่มลงใน. NET ได้ในตอนนี้
IDisposable
ไม่มีDisposed
คุณสมบัติก็คือมันจะถูกมองว่าแปลกที่มีวัตถุที่การโทรDispose
ไม่ได้ตั้งค่าคุณสมบัติดังกล่าวtrue
แต่ต้องการให้วัตถุนั้นติดตามว่าDispose
ถูกเรียกในกรณีที่ มิฉะนั้นพวกเขาจะไม่มีเหตุผลที่จะดูแลจะเพิ่มต้นทุนที่สำคัญและผลประโยชน์เพียงเล็กน้อย
ฉันเห็นว่ามันเก่า แต่ฉันไม่เห็นคำตอบ อ็อบเจ็กต์ที่ใช้แล้วทิ้งบางอย่างเช่น DataSet อาจมีเหตุการณ์ที่ถูกทิ้งที่คุณสามารถแนบ
class DisposeSample : IDisposable
{
DataSet myDataSet = new DataSet();
private bool _isDisposed;
public DisposeSample()
{
// attach dispose event for myDataSet
myDataSet.Disposed += MyDataSet_Disposed;
}
private void MyDataSet_Disposed(object sender, EventArgs e)
{
//Event triggers when myDataSet is disposed
_isDisposed = true; // set private bool variable as true
}
public void Dispose()
{
if (!_isDisposed) // only dispose if has not been disposed;
myDataSet?.Dispose(); // only dispose if myDataSet is not null;
}
}
Disposed
เหตุการณ์เป็นสมาชิกของSystem.ComponentModel.IComponent
อินเทอร์เฟซ
สิ่งที่ฉันต้องการจะทำคือประกาศวัตถุโดยไม่ต้องเริ่มต้นพวกเขา Nothing
แต่ตั้งค่าเริ่มต้นของพวกเขาไป จากนั้นในตอนท้ายของลูปฉันเขียน:
If anObject IsNot Nothing Then anObject.Dispose()
นี่คือตัวอย่างที่สมบูรณ์:
Public Sub Example()
Dim inputPdf As PdfReader = Nothing, inputDoc As Document = Nothing, outputWriter As PdfWriter = Nothing
'code goes here that may or may not end up using all three objects,
' such as when I see that there aren't enough pages in the pdf once I open
' the pdfreader and then abort by jumping to my cleanup routine using a goto ..
GoodExit:
If inputPdf IsNot Nothing Then inputPdf.Dispose()
If inputDoc IsNot Nothing Then inputDoc.Dispose()
If outputWriter IsNot Nothing Then outputWriter.Dispose()
End Sub
วิธีนี้ยังใช้งานได้ดีในการวางวัตถุหลักไว้ที่ด้านบนของกิจวัตรโดยใช้สิ่งเหล่านี้ภายในTry
กิจวัตรแล้วทิ้งในFinally
บล็อก
Private Sub Test()
Dim aForm As System.Windows.Forms.Form = Nothing
Try
Dim sName As String = aForm.Name 'null ref should occur
Catch ex As Exception
'got null exception, no doubt
Finally
'proper disposal occurs, error or no error, initialized or not..
If aForm IsNot Nothing Then aForm.Dispose()
End Try
End Sub
Using
คำสั่ง? มีอยู่อย่างแน่นอนในปี 2013 เมื่อคำตอบนี้ถูกเขียนขึ้น
inputPdf
ถูกตั้งค่าเป็นค่า (นอกเหนือจาก Nothing) คำตอบของคุณจะแสดงให้เห็นว่าไม่มีทางรู้ว่าinputPdf
ถูกกำจัดไปหรือไม่ คุณสามารถแก้ไขบางส่วนได้โดยการตั้งค่าinputPdf = Nothing
หลังจากกำจัดทิ้ง อย่างไรก็ตามสิ่งนี้จะไม่ช่วยให้ตัวแปรอื่นใดที่ถูกชี้ไปที่วัตถุเดียวกันinputPdf
ด้วย นั่นคือถ้าคุณทำ: inputPdf = New PdfReader
, Dim pdf2 As PdfReader = inputPdf
, inputPdf.Dispose
, inputPdf = Nothing
ก็จะยังคงเป็นวิธีที่จะรู้ว่าไม่pdf2
เป็นที่จำหน่าย (มันเป็นวัตถุเช่นเดียวinputPdf
)
bool IsDisposed { get; }
System.IDisposable