廃棄されたオブジェクトへの参照であるかどうかを確認する方法、またはその他の軽量な方法はありますか?
PS-これは単なる好奇心です(本番コードではなく、よく眠れます)。はい、ObjectDisposedException
オブジェクトのメンバーにアクセスしようとすると、キャッチできることを知っています。
廃棄されたオブジェクトへの参照であるかどうかを確認する方法、またはその他の軽量な方法はありますか?
PS-これは単なる好奇心です(本番コードではなく、よく眠れます)。はい、ObjectDisposedException
オブジェクトのメンバーにアクセスしようとすると、キャッチできることを知っています。
Dispose
メソッドは、取得したがまだ解放されていないすべてのリソースを解放するようにオブジェクトに指示します。オブジェクトがリソースを保持しない場合、そのDispose
メソッドは通常何もする必要はありません。タイプが宣言しvoid IDisposable.Dispose() {};
ている場合は、IDisposable
インスタンスごとのオーバーヘッドなしで無視できます。呼び出しのIsDisposed
後にtrueになると予想されたプロパティではDispose
、他の方法では無視できる多くのタイプのすべてのインスタンスに、それ以外の場合は不要なブールフラグを追加する必要がありますDispose
。
IDisposable
それが最初に破棄されたかどうかをどのように確認できますか?そうではないと想定して例外をキャッチするのではなく?それとも、どういうわけかあなたはそれが処分されているかどうかを常に知る必要があるように生涯を管理することを意図していますか?
IsDisposed
フラグは、おそらく成功することができない業務に時間を浪費するからコードを防ぐのに役立つかもしれませんが、一つは、まだオブジェクトが間に配置されます場合に例外を処理する必要がありますIsDisposed
チェックし、それを使用しようとする試み。
WeakReference
ここに関連しているようです。これは正確にIDiposeされた検出器ではありませんが、GCされているかどうかはわかります
回答:
System.Windows.Forms.Control
が呼び出された後にtrueに設定されるIsDisposed
プロパティがあります。独自のIDisposableオブジェクトで、同様のプロパティを簡単に作成できます。Dispose()
これを可能にするものは何も組み込まれていません。内部のdisposedフラグを反映する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プロパティ(または同様のもの-名前は単なる慣例です)を提供しない場合、あなたは知る方法がありません。
ただし、それがクラスであり、正規のIDisposable実装に従っている場合は、_disposedまたは_isDisposedフィールドをプロパティとして公開して確認してください。
このDispose
メソッドは、オブジェクトが破棄される前に必要となるクリーンアップを実行するために必要です。クリーンアップが必要ない場合は、何もする必要はありません。Dispose
メソッドが他の方法で何もしない場合でも、オブジェクトが破棄されたかどうかを追跡するようにオブジェクトに要求すると、IDisposable
非常に限られた利点のために多くのオブジェクトがフラグを追加する必要があります。
IDisposable
2つのプロパティが含まれていると便利だったかもしれません。1つはオブジェクトを破棄する必要があるかどうかを示し、もう1つはオブジェクトが破棄によって役に立たなくなっていないことを示します。廃棄が実際に何かを行うオブジェクトの場合、両方の値は最初はtrueであり、その後はfalseになりますDispose
。廃棄でクリーンアップを行う必要がないオブジェクトの場合、フラグをどこにも格納しなくても、最初のメソッドは常にfalseを返し、2番目のメソッドは常にtrueを返す可能性があります。しかし、今はそれらを.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
です。