많은 사람들이 Dispose() 메서드가 Close() 메서드 내에서 내부적으로 호출된다고 생각하므로 본질적인 차이는 없습니다! 사실 이 견해는 그다지 정확하지 않습니다.
일부 클래스의 경우 Close()와 Dispose() 사이에 본질적인 차이가 없는 것이 사실이지만 일부 클래스의 경우 그렇지 않습니다!
먼저 우리가 가장 자주 사용하는 SqlConnection의 Close() 메서드와 Dispose() 메서드의 차이점을 살펴보겠습니다.
SqlConnection 클래스의 Dispose() 메서드는 Component 클래스에서 상속됩니다. 소스 코드는 다음과 같습니다.
공공 무효 Dispose() {
Dispose(true); //매개변수를 사용하여 Dispose 오버로드를 호출합니다.
GC.SuppressFinalize(this); //지정된 객체의 종료자를 호출하지 않도록 시스템에 요청합니다.
}
보호된 가상 무효 Dispose(bool disposing) {
if (처분) {
잠금(이것) {
if (사이트 != null && site.Container != null) {
site.Container.Remove(this);
}
if (이벤트 != null) {
EventHandler 핸들러 = (EventHandler)events[EventDisposed];
if (handler != null) handler(this, EventArgs.Empty);
}
}
}
}
MSDN의 SqlConnection 클래스의 Close() 메서드에 대한 설명은 다음과 같습니다.
데이터베이스에 대한 연결을 닫습니다. 이는 열려 있는 연결을 닫는 데 선호되는 방법입니다. SqlConnection이 범위를 벗어나면 닫히지 않습니다. 왜냐하면
따라서 Close 또는 Dispose를 호출하여 연결을 명시적으로 닫아야 합니다. 닫기와 삭제는 기능적으로 동일합니다. 연결 풀 값인 경우
풀링 true 또는 yes로 설정된 경우 기본 연결이 연결 풀로 반환됩니다. 반면 Pooling이 false 또는 no로 설정된 경우에는
서버에 대한 기본 연결이 닫힙니다.
설명을 보면 Close() 메서드와 Dispose() 메서드는 유사한 것으로 보이지만 실제로는 연결을 닫는 기능만 동일합니다.
() 메소드 소스 코드:
public void Close() 재정의 {
IntPtr hscp;
Bid.ScopeEnter(out hscp, "<sc.SqlConnection.Close|API> %d#" , ObjectID);
노력하다 {
SqlStatistics 통계 = null;
RuntimeHelpers.PrepareConstrainedRegions();
노력하다 {
#if 디버그
objectinitialReliabilitySlotValue = 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) {
InnerConnection.CloseConnection(this, ConnectionFactory);
}
// OnStateChange 때문에 GC.KeepAlive(this)가 필요하지 않습니다.
if (null != 통계) {
ADP.TimerCurrent(out _statistics._closeTimestamp);
}
#if 디버그
}
마지막으로 {
Thread.SetData(TdsParser.ReliabilitySlot,initialReliabilitySlotValue);
}
#endif //디버그
}
잡기 (System.OutOfMemoryException e) {
중단(e);
던지다;
}
잡기 (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() 메서드를 호출한 후에는 더 이상 연결을 사용할 수 없습니다!
또 다른 중요한 차이점은 Close() 메서드가 GC.SuppressFinalize(this);를 호출하지 않는 경우 이로 인한 직접적인 결과는 가비지라는 것입니다.
재활용하는 동안 종료 작업이 필요하며, 이로 인해 이 인스턴스의 "생성 기간"이 증가하여 이 개체의 재활용 시간이 크게 지연됩니다!
SqlConnection 클래스의 경우 나중에 이 연결을 사용해야 하는 경우 Close() 메서드를 사용하여 연결을 일시적으로 닫을 수 있습니다.
이 연결을 사용하려면 먼저 Dispose() 메서드를 사용하여 리소스를 해제할 수 있습니다. 물론 using 키워드를 사용하면 이 프로세스를 단순화할 수 있습니다.
OleDbConnection 클래스와 OdbcConnection 클래스의 소스 코드를 찾지 못했지만 SqlConnection 클래스와 비슷할 것입니다!
일반적으로 사용되는 클래스를 살펴보고 FileStream 클래스의 Close() 메서드와 Dispose() 메서드 간의 차이점을 살펴보겠습니다.
FileStream 클래스의 Close() 메서드는 Stream 클래스에서 상속됩니다. 소스 코드는 다음과 같습니다.
공개 가상 무효 닫기()
{
폐기(true);
GC.SuppressFinalize(this);
}
FileStream 클래스의 Dispose() 메서드는 Stream 클래스에서 상속됩니다. 소스 코드는 다음과 같습니다.
공공 무효 처리()
{
닫다();
}
이는 표준 Dispose 모드의 구현입니다. Close() 메서드는 매개 변수를 사용하여 Dispose 메서드를 호출한 다음 GC.SuppressFinalize를 호출합니다.
(this); 지정된 개체의 종료자를 호출하지 않도록 시스템에 요청합니다. Dispose() 메서드는 Close() 메서드를 직접 호출합니다!
FileStream 클래스의 경우 Close() 메서드와 Dispose() 메서드 사이에 차이가 없습니다!