まあ、ファイナライズは廃棄ではないので、廃棄されません。
にはファイナライザーがありますが、のコンストラクターでSystem.ComponentModel.Component
は抑制されていSQLConnection
ます。これは、100% 確実に必要ないことがわかっているファイナライザーを使用して継承する場合は良い考えですが、そうでない場合は悪い考えです。この場合、それは良い考えです。
SqlConnection
ただし、これは「実際の」接続のラッパーであることを忘れないでください。実際、さまざまな接続状態を表す一連の変化するオブジェクトのラッパーである可能性が最も高いです。これは、「実際の」接続を効率的にプールできるようにするメカニズムの一部です。これは、呼び出すOpen()
たびにプールから関連するオブジェクトを取得し、呼び出すたびにClose()
(直接、Dispose()
スコープから、またはスコープを離れることによって) using
) それを返します。
ここで、管理されていないリソースまたは GC の関心事ではないものを直接保持するオブジェクトのみをファイナライズする必要があることを思い出してください。SqlConnection
( の状態に応じてSqlConnection
) アンマネージ リソース (または実際には、クラスのネストを介してより深い) を保持するオブジェクトである可能性があるオブジェクトを保持します。SqlConnection
したがって、それ自体をファイナライズする必要はありません。SqlConnection
openがopen でなくなる可能性のある 3 つの方法を考えてみましょうSqlConnection
。
Close()
と呼ばれます。これにより、実際の接続がすぐにプールに返されます (プールがない場合は閉じられます)。
Dispose()
と呼ばれます。これはClose()
同じ効果で呼び出します。
- オブジェクトはガベージ コレクションされます。
さて、3 番目のケースでは、オブジェクトは実際の接続を持つオブジェクトへの参照を保持しています。また、そうする唯一のオブジェクトでもあります。そのため、そのオブジェクトもガベージ コレクションの対象になります。ファイナライザーがある場合 (これ以上の巧妙なトリックが行われていないとは思いませんが、おそらくそうです)、そのファイナライザーによってファイナライザー キューに入れられ、最終的にファイナライズされます。
ファイナライザーがある場合SqlConnection
、実際の効果は次のとおりです。
- バグのあるコードが発生する可能性があります (ファイナライズ可能なメンバーがファイナライズされているかどうかわからないため、ファイナライザー コードでファイナライズ可能なメンバーを処理するのは困難です)。
- 物事が遅くなる可能性があります (実際の接続はいずれにせよファイナライズされますが、せいぜいファイナライズと GC が遅くなるだけです)。
- とにかくここで何もする必要はありません (実際の接続はここで何の助けもなしに確定されます)。
したがって、ファイナライザーを に置くことSqlConnection
は、勝利なしの敗北です。また、実際の接続が最終的に完了することを願っています。
とはいえ、まだ理想にはほど遠いものであり、接続がリークする可能性は依然として非常に高いです。Close()
電話や処分ができない理由を正確に説明していただけますか? 接続を管理するコードが close を呼び出さない可能性はありますか (オブジェクトはその日をどこかで終了し、そこで閉じる必要があります)。
IDataReader
から供給される やオブジェクトが完了できるようにするために、それを存続させる必要がありますIDataReader
か? その場合、CommandBehavior.CloseConnection
フラグを使用して、リーダーを閉じる (または破棄する) ことで接続を閉じることができますか? この後者のケースは、接続がスコープを未処理のままにしなければならなかったことを思い出すことができる唯一のケースに関するものです。