多くの人は、Dispose() メソッドは Close() メソッドの内部で呼び出されるので、本質的な違いはないと考えています。実際、この見方はあまり正確ではありません。
一部のクラスでは、Close() と Dispose() の間に本質的な違いがないことは事実ですが、一部のクラスではそうではありません。
まず、最も頻繁に使用する SqlConnection の Close() メソッドと Dispose() メソッドの違いを見てみましょう。
SqlConnection クラスの Dispose() メソッドは Component クラスから継承されます。ソース コードは次のとおりです。
public void Dispose() {
Dispose(true); // パラメータを指定して Dispose のオーバーロードを呼び出します。
GC.SuppressFinalize(this); //指定されたオブジェクトのファイナライザーを呼び出さないようにシステムに要求します。
}
protected virtual void Dispose(bool disposing) {
if (処分) {
ロック(これ) {
if (サイト != null && site.Container != null) {
site.Container.Remove(this);
}
if (イベント != null) {
EventHandler ハンドラー = (EventHandler)events[EventDissolved];
if (ハンドラー != null) ハンドラー(this, EventArgs.Empty);
}
}
}
}
MSDN の SqlConnection クラスの Close() メソッドの説明は次のとおりです。
データベースへの接続を閉じます。これは、開いている接続を閉じる場合に推奨される方法です。 SqlConnection がスコープ外になった場合、SqlConnection は閉じられません。なぜなら
したがって、Close または Dispose を呼び出して接続を明示的に閉じる必要があります。 Close と Dispose は機能的に同等です。接続プールの値が
Pooling true または yes に設定すると、基礎となる接続が接続プールに返されます。一方、Pooling が false または no に設定されている場合、
サーバーへの基礎となる接続が閉じられます。
説明からすると、Close() メソッドと Dispose() メソッドは似ているように見えますが、実際には、接続を閉じる機能が同じであるだけです。Close を見てみましょう。
() メソッドのソースコード:
オーバーライド public void Close() {
IntPtr hscp;
Bid.ScopeEnter(out hscp, "<sc.SqlConnection.Close|API> %d#" , ObjectID);
試す {
SqlStatistics 統計 = null;
RuntimeHelpers.PrepareConstrainedRegions();
試す {
#if デバッグ
オブジェクトのinitialReliabilitySlotValue = Thread.GetData(TdsParser.ReliabilitySlot);
RuntimeHelpers.PrepareConstrainedRegions();
試す {
Thread.SetData(TdsParser.ReliabilitySlot, true);
#endif //デバッグ
統計 = SqlStatistics.StartTimer(統計);
// ここでのロックは、command.cancel / connection.close から保護するためのものです。
競合状態
// これが完了すると、SqlInternalConnectionTds は閉じるときに OpenBusy に設定されます。
以下のキャストが失敗するとどうなるか、
// コマンドはキャンセルできなくなります。
閉じる操作をキャンセルすることはできますが、これは
// Whidbey RTM の範囲外。その他については (SqlCommand::Cancel) を参照してください。
ロック。
ロック (内部接続) {
InnerConnection.CloseConnection(this, ConnectionFactory);
}
// OnStateChange のため GC.KeepAlive(this) は必要ありません
if (null != 統計) {
ADP.TimerCurrent(out _statistics._closeTimestamp);
}
#if デバッグ
}
ついに {
Thread.SetData(TdsParser.ReliabilitySlot、initialReliabilitySlotValue);
}
#endif //デバッグ
}
catch (System.OutOfMemoryException e) {
中止(e);
投げる;
}
catch (System.StackOverflowException e) {
中止(e);
投げる;
}
catch (System.Threading.ThreadAbortException e) {
中止(e);
投げる;
}
ついに {
SqlStatistics.StopTimer(統計);
}
}
ついに {
SqlDebugContext sdc = _sdc;
_sdc = null;
Bid.ScopeLeave(ref hscp);
if (sdc != null) {
sdc.Dispose();
}
}
}
Close() メソッドが Dispose() メソッドを呼び出していないことがわかりますが、 sdc.Dispose(); という行がありますが、これは SqlDebugContext を解放するだけです。
インスタンスは、SqlConnection.Dispose() メソッドとは何の関係もありません。
それで、違いは何ですか?
Close() メソッドは接続を閉じるだけで、その後、接続は接続プールに保存されるため、Close() メソッドを呼び出した後も、引き続き接続を渡すことができます。
Open() メソッドを使用して接続を開き、Dispose() メソッドを呼び出した後、接続は使用できなくなります。
もう 1 つの重要な違いは、Close() メソッドが GC.SuppressFinalize(this); を呼び出さない場合、その直接の結果がガベージになることです。
リサイクル中に終了操作が必要になるため、このインスタンスの「世代年齢」が増加し、その結果、このオブジェクトのリサイクル時間が大幅に遅延します。
SqlConnection クラスの場合、今後この接続を使用する必要がある場合は、Close() メソッドを使用して接続を一時的に閉じることができます。
この接続を使用するには、まず Dispose() メソッドを使用してリソースを解放します。もちろん、using キーワードを使用してこのプロセスを簡素化することもできます。
OleDbConnection クラスと OdbcConnection クラスのソース コードは見つかりませんでしたが、SqlConnection クラスに似ているはずです。
一般的に使用されるクラスを見て、FileStream クラスの Close() メソッドと Dispose() メソッドの違いを見てみましょう。
FileStream クラスの Close() メソッドは Stream クラスから継承されます。ソース コードは次のとおりです。
public virtual void Close()
{
破棄(true);
GC.SuppressFinalize(this);
}
FileStream クラスの Dispose() メソッドは Stream クラスから継承されます。ソース コードは次のとおりです。
public void Dispose()
{
近い();
}
これは、標準の Dispose モードの実装です。Close() メソッドはパラメータを指定して Dispose メソッドを呼び出し、その後 GC.SuppressFinalize を呼び出します。
(this); 指定されたオブジェクトのファイナライザーを呼び出さないようにシステムに要求します。 Dispose() メソッドは Close() メソッドを直接呼び出します。
FileStream クラスの場合、Close() メソッドと Dispose() メソッドの間に違いはありません。