มีวิธีการหรือวิธีอื่นที่มีน้ำหนักเบาในการตรวจสอบว่ามีการอ้างอิงถึงวัตถุที่กำจัดทิ้งหรือไม่?
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