2016-12-14 7 views
0

私はガベージコレクションの理解を深め、管理されていないリソース&を管理しようとしています。また、「低レベル」のプログラミングやそのようなものに興味を持っているので、メモリ管理に関する「適切な設計原則」私はあなたがusingブロックまたはこれらのアンマネージリソースを確保するためのいくつかの他のソリューションを使用するをを想定していることを理解しDisposeを呼び出すのは正確に何ですか?

は、実際に配置されたのですか、私はボンネットの下に何が起こっているのか理解していません。

私はこの記事を見ていた

:MSDNのImplementing a Dispose Methodと、この特定の行で混乱していた:リソースが常に適切にクリーンアップされることを確保するために

、Disposeメソッドは、スローせずに呼び出し可能な複数回でなければなりません例外。

彼らは処分パターンを提供するサンプルコードを見てみましょう:私は上記の引用されたテキストは、基本的に私たちができるように、私たちはbool disposedプロパティを追加しました」、と言っているものを信じる

class DerivedClass : BaseClass 
{ 
    // Flag: Has Dispose already been called? 
    bool disposed = false; 

    // Instantiate a SafeHandle instance. 
    SafeHandle handle = new SafeFileHandle(IntPtr.Zero, true); 

    // Protected implementation of Dispose pattern. 
    protected override void Dispose(bool disposing) 
    { 
     if (disposed) 
     return; 

     if (disposing) 
     { 
     handle.Dispose(); 
     // Free any other managed objects here. 
     } 

     // Free any unmanaged objects here. 

     disposed = true; 

     // Call base class implementation. 
     base.Dispose(disposing); 
    } 
} 

それはtrueもしそうならreturnだかどうかを確認します。それは、その後falseをなら、我々は実際のリソースを処分。我々は

0123「ではない実際に何かの処分を複数回行うその方法を

しかし、これは私には意味がありませんでした。オブジェクトを取り除いてしまったら、もう一度Disposeと呼ぶことができますか?記事から引用されたテキストを考えると、理にかなって -

var cmd = new SqlCommand(); 
cmd.Dispose(); 
cmd.Dispose(); 

これは、コンパイルし、問題なく実行されます。調査するために

は、私は以下の3行を含むコンソールアプリケーションを書きました。しかし、私はが実際にはが起こっていることを理解していません。

私はブレークポイントを設定し、各行を踏んだ。最初のDisposeが呼び出された後、私はcmdnullであることをVisual Studioのローカルウィンドウが私に伝えることを期待しました。この思考の列に沿って、私は自分自身に尋ねました。「Disposenullに電話するにはどうすればいいですか?明らかに、あなたはできません。では何が起こっているのですか? cmdはなぜ初めて処分された後にSqlCommandオブジェクトですか?

enter image description here

Disposeがやっている、と私は私の物を処分してしまった場合どう正確なぜまだ、すべての意図や目的のために存在するように見えるのでしょうか?

なぜ/次のようにコンパイルして問題なく実行できますか?

var cmd = new SqlCommand(); 
cmd.Dispose(); 
cmd.CommandText = "I figured this would throw an exception but it doesn't"; 
+1

"under the hood"はありません。魔法は関係なく、それは他のどのような方法でもあります。 'Dispose'メソッドを書く人は、それを適切に実装する必要があります - 適切な' CloseHandle'関数などをすべて呼び出します。他の方法で "this reference"を "null"に変更できますか?もちろん違います。なぜあなたは 'Dispose'がそれをすることができると思いますか?単なる方法です。 – Luaan

+1

Luaanの説明に加えて、より大きな画像はhttp://stackoverflow.com/questions/538060/proper-use-of-theididposable-interfaceも参照してください。 –

+1

あなたは最悪の可能性のある例について、何も役に立ちませんでした(https://referencesource.microsoft.com/#System.Data/System/Data/SqlClient/SqlCommand.cs,1101)。おそらく、.NET 1.0では非常に異なったことをしました。しかし、あなたがそれを廃棄した後でも、オブジェクトを使用し続けることは確かにありません。うまくいけばそれはやや明白です。 ObjectDisposedExceptionをスローすることがあります。メンバーが「重い」ものを何もしないので、そうでないかもしれません。意図的に間違っていることはそれほど有用ではありません。 –

答えて

2

:あなたはこのようなものにするために使用して文を検討することもでき。これにより、管理されていないリソースをきれいに保つことが容易になります。 しかし、Disposeは他の方法と同じで、デストラクタ/ファイナライザと混同しないでください(これは明らかにあなたが期待したものです)

+0

"...デストラクタ/ファイナライザと混同しないでください "〜私はこれがここでの問題だと思う。[' Object.Finalize']に関する読者(https://msdn.microsoft.com/en-us/library/system.object.finalize (v = vs.110).aspx)私は、最終的に 'Finalize'と呼ばれる、' Dispose '(一連の' base.Dispose() '呼び出しを通して)、または明示的に'Dispose'は文字通り' using'ステートメントの文法砂糖の一部にすぎません。 – sab669

+0

はい、ありますよね:-) –

+1

@ sab669実際には実際には通常は逆もあります - ユーザーが呼び出し可能ではないファイナライザは、しばしばすべてのクリーンアップロジックを1か所に保持するためにDisposeメソッドを呼び出します.NETでのFinalizerは、何かが間違っていてもリソースは処分されます(あなたは適切な 'Dispose'メソッドを呼び出すのを忘れてしまいました)。 gsですが、これが彼らのために設計された唯一のものであり、ファイナライザで多くの保証を失うので、安全なファイナライザを書くことはまったく簡単なことではありません。 「これ」は「ヌル」にすることもできます:) – Luaan

1

using文はあなたのためにそれを呼び出すことができるという事実を除いてDisposeについての特別なことは何もありません。それ以外は、他の.NET関数とまったく同じです。それは魔法のように任意の変数をnullに設定せず、オブジェクトが再び使用された場合などに例外がスローされる原因になります。

同様に、IDisposableは、usingステートメントのオブジェクトがそれを実装する必要がある点を除いて、特別なインターフェイスではありません。既にダークファルコンが述べた - - あなたが使用してブロック内のクラスの使用方法をカプセル化する際にIDisposableインタフェースは、いくつかの消費クラスとによって呼び出されている

// using(var a = somethingDisposable()) {otherCode();} 
var a = somethingDisposable(); 
try 
{ 
    otherCode(); 
} 
finally 
{ 
    if(a != null) 
     ((IDisposable)a).Dispose(); 
} 
+0

しかし、それはどういう意味ですか。 Disposeは何をしますか? *ガベージコレクタが実行するときはいつでも、それらのアイテムを処理するように、オブジェクトのGenerationをインクリメントするだけですか? – sab669

+1

いいえ、それは私が言ったように、ガベージコレクタとの相互作用が全くゼロです。これは単なる別の.NETメソッドです。 'using'ステートメントの素晴らしい構文を除いては特別なものはありません。 –

+1

'Dispose'はあなたに何をするか指示します。単なる方法です。通常は、管理されていないリソースを制御された方法で削除するために使用します(つまり、使用ブロック内でインスタンスを操作する場合)。 –

関連する問題