원칙 15: using 과 try / finally 를 사용 하여 자원 정리

10141 단어 finally
원칙 15: using 과 try / finally 사용 자원 정리
 
By D.S.Qiu
타인 의 노동 을 존중 하고 오리지널 을 지지 하 며 전재 할 때 출처 를 밝 혀 주 십시오.http://dsqiu.iteye.com
 
      비 위탁 관리 자원 형식 은 IDisposable 인터페이스의 Dispose () 방법 으로 풀 어야 합 니 다.NET 의 이 규칙 으로 인해 자원 을 방출 하 는 직책 은 유형 과 시스템 이 아니 라 유형의 사용자 이다.따라서 언제든지 사용 하 는 유형 에 Dispose () 방법 이 있 으 면 Dispose () 를 호출 하여 자원 을 방출 할 책임 이 있 습 니 다.dispose () 가 호출 될 때 using 구문 이나 try / finally 블록 을 사용 하도록 하 는 가장 좋 은 방법 입 니 다.
 
      비 위탁 관리 자원 을 포함 하 는 모든 유형 은 IDisposable 인 터 페 이 스 를 실현 해 야 합 니 다.또한, 이 유형 들 을 적절하게 회수 하지 않 으 면 수 동적 으로 분석 함 수 를 만 들 수 있 습 니 다.이 대상 들 을 회수 하 는 것 을 잊 어 버 리 면, 이 비 메모리 자원 들 은 늦게 분석 함수 가 실 행 될 때 방출 됩 니 다.이것 은 이 대상 들 이 메모리 에 더 오래 머 무 르 게 하고 응용 프로그램 이 시스템 자원 을 너무 많이 차지 해서 느 려 질 것 이다.
 
       다행히도 C \ # 언어 디자이너 는 자원 방출 을 표시 하 는 것 이 흔 한 조작 이라는 것 을 알 고 있다.그들 은 언어 에 키 워드 를 추가 해서 더욱 쉬 울 것 이다.
 
public void ExecuteCommand(string connString, string commandString)
{ 
	SqlConnection myConnection = new SqlConnection(connString);
	SqlCommand mySqlCommand = new SqlCommand(commandString, myConnection);
	myConnection.Open(); 
	mySqlCommand.ExecuteNonQuery();
}

  
 
       이 예 에서 회수 가능 한 대상 두 개가 적절하게 정리 되 지 않 았 습 니 다: SqlConnection 과 SqlCommand.이 두 대상 은 석조 함수 가 호출 될 때 까지 메모리 에 머 물 러 있 을 것 이다.(이 두 종 류 는 모두 System. Component Model. Component 에서 분석 함 수 를 계승 합 니 다.
 
        명령 과 연결 이 끝 날 때 Dispose 를 호출 하여 이 문 제 를 복구 합 니 다.
 
public void ExecuteCommand(string connString, string commandString)
{
	SqlConnection myConnection = new SqlConnection(connString);
	SqlCommand mySqlCommand = new SqlCommand(commandString, myConnection);
	myConnection.Open(); 
	mySqlCommand.ExecuteNonQuery();
	mySqlCommand.Dispose(); 
	myConnection.Dispose();
}

  
 
       이 SQL 명령 이 실행 되 지 않 으 면 잘 처 리 됩 니 다. 이 때 는 위의 디 스 포 스 () 가 실행 되 지 않 습 니 다. using 문 구 를 사용 하면 디 스 포 스 () 가 호출 될 수 있 습 니 다. using 문 구 를 사용 하면 대상 을 할당 합 니 다. C \ # 컴 파 일 러 는 try / finally 블록 을 포함 합 니 다.
 
public void ExecuteCommand(string connString, string commandString)
{
	using (SqlConnection myConnection = new SqlConnection(connString)) 
	{
		using (SqlCommand mySqlCommand = new SqlCommand(commandString, myConnection))
		{
			myConnection.Open(); 
			mySqlCommand.ExecuteNonQuery();
		} 
	}
}

  
 
       함수 에서 회수 가능 한 대상 을 사용 할 때 using 블록 은 가장 간단 한 방법 으로 대상 이 적절하게 회수 되 는 것 을 확보 합 니 다. using 문 구 는 try / finally 블록 패키지 가 분 배 된 대상 을 만 듭 니 다. 아래 두 코드 의 IL 코드 는 같 습 니 다.
 
SqlConnection myConnection = null;
// Example Using clause: 
using (myConnection = new SqlConnection(connString)) 
{
	myConnection.Open(); 
}
// example Try / Catch block: 
try 
{
	myConnection = new SqlConnection(connString); 
	myConnection.Open();
}
finally 
{
	myConnection.Dispose(); 
}

  
 
       IDisposable 형식 에 using 문 구 를 사용 하지 않 으 면 C \ # 컴 파일 러 가 잘못 보 고 됩 니 다. 예 를 들 어:
 
// Does not compile: 
// String is sealed, and does not support IDisposable. 
using (string msg = "This is a message")
Console.WriteLine(msg);

 
 
       using 문 구 는 컴 파일 시기 유형 에서 IDisposable 인 터 페 이 스 를 실현 해 야 정상적으로 작 동 합 니 다. 임의의 대상 에 게 사용 할 수 없습니다:
 
// Does not compile. 
// Object does not support IDisposable. 
using (object obj = Factory.CreateResource())
Console.WriteLine(obj.ToString());
 

 
 
       빠 른 보호 방법 은 as 문 구 를 사용 하여 안전 하고 회수 가능 한 대상 으로 전환 할 수 있 습 니 다.
 
// The correct fix. 
// Object may or may not support IDisposable.
object obj = Factory.CreateResource();
using (obj as IDisposable) 
Console.WriteLine(obj.ToString());

  
 
       obj 가 IDisposable 을 실현 하면 using 문 구 는 청소 코드 를 만 듭 니 다. 그렇지 않 으 면 using 문 구 는 using (null) 으로 바 뀌 었 습 니 다. 안전 하고 아무런 처리 도 하지 않 습 니 다. using 블록 패키지 대상 을 사용 하 는 것 이 정확 한 지 확실 하지 않다 면 안전 을 위해 서 입 니 다. 그렇게 하 는 것 이 정확 하고 앞의 방법 처럼 using 패키지 대상 을 사용 합 니 다.
 
       이것 은 단지 간단 한 상황 을 소개 하 는 것 입 니 다. 대상 내 에서 회수 가능 한 부분 대상 을 사용 할 때 using 문 구 를 사용 하여 대상 을 감 싸 는 것 입 니 다. 지금 은 몇 가지 복잡 한 용법 을 봅 니 다. 첫 번 째 예 에서 두 개의 서로 다른 대상 을 회수 해 야 합 니 다. 연결 과 명령. 앞의 방법 은 두 개의 using 문 구 를 사용 하여 회수 해 야 할 두 개의 대상 을 각각 안에 두 는 것 입 니 다. 각각 using 어 를 사용 합 니 다.문장 에 try / finally 블록 이 생 성 됩 니 다. 다음 코드 를 쓴 것 과 같 습 니 다.
 
public void ExecuteCommand(string connString, string commandString)
{ 
	SqlConnection myConnection = null;
	SqlCommand mySqlCommand = null; 
	try 
	{
		myConnection = new SqlConnection(connString); 
		try 
		{
			mySqlCommand = new SqlCommand(commandString, myConnection);
			myConnection.Open(); 
			mySqlCommand.ExecuteNonQuery();
		} 
		finally 
		{
		if (mySqlCommand != null) 
			mySqlCommand.Dispose();
		} 
	} 
	finally 
	{
	if (myConnection != null) 
		myConnection.Dispose();
	} 
}

  
 
       모든 using 문 구 는 끼 워 넣 은 try / finally 블록 을 만 듭 니 다. 다행히 우 리 는 IDisposable 을 실현 하 는 두 개의 대상 을 분배 하 는 일이 거의 없습니다. 이 경우 정상적으로 작 동 할 수 있 기 때문에 허용 할 수 있 습 니 다. 그러나, IDisposable 을 실현 하 는 여러 개의 대상 을 분배 하려 면 아주 나 쁜 실현 이 될 것 입 니 다. 저 는 try / finally 를 쓰 는 것 을 더 좋아 합 니 다.블록:
public void ExecuteCommand(string connString, string commandString)
{
	SqlConnection myConnection = null;
	SqlCommand mySqlCommand = null; 
	try 
	{
		myConnection = new SqlConnection(connString); 
		mySqlCommand = new SqlCommand(commandString,
		myConnection);
		myConnection.Open(); 
		mySqlCommand.ExecuteNonQuery();
	} 
	finally 
	{
		if (mySqlCommand != null) 
			mySqlCommand.Dispose();
		if (myConnection != null) 
			myConnection.Dispose();
	} 
}

 
 
       이러한 문법 을 버 릴 수 있 는 유일한 이 유 는 using 과 as 문 구 를 쉽게 사용 할 수 있 기 때문이다.
 
분명 해 보이 지만 교활 한 문제 가 있 을 수 있 습 니 다. SqlCommand ()구조 가 이상 한 SqlConnection 대상 을 던 지면 회수 되 지 않 습 니 다. my Connection 이 생 성 되 었 지만 SqlCommand 구조 함수 가 실 행 될 때 코드 는 using 블록 에 들 어가 지 않 습 니 다. using 블록 이 제대로 구성 되 지 않 으 면 Dispose 호출 이 건 너 뜁 니 다. IDisposable 을 실현 하 는 대상 의 분 배 는 using 블록 이나 try 블록 에 있어 야 합 니 다. 그렇지 않 으 면 자원 유출 이 발생 합 니 다.일어 날 겁 니 다.
public void ExecuteCommand(string connString, string commandString)
{
	// Bad idea. Potential resource leak lurks! 
	SqlConnection myConnection = new SqlConnection(connString);
	SqlCommand mySqlCommand = new SqlCommand(commandString,myConnection); 
	using (myConnection as IDisposable) 
	using (mySqlCommand as IDisposable) 
	{
		myConnection.Open(); 
		mySqlCommand.ExecuteNonQuery();
	} 
}

 
       지금까지 가장 흔히 볼 수 있 는 두 가지 상황 을 배 웠 습 니 다. 한 함수 에 하나의 회수 가능 한 대상 만 할당 할 때 using 문 구 를 사용 하 는 것 이 가장 좋 은 방법 입 니 다. 한 방법 에서 여러 대상 을 할당 하려 면 using 블록 을 만 들 거나 try / finally 블록 을 만 드 는 것 이 좋 습 니 다.
 
       재 활용 가능 한 대상 에 따라 약간의 차이 가 있 을 수 있 습 니 다. 일부 유형 은 Dispose 방법 과 Close 방법 을 동시에 지원 하여 자원 을 방출 합 니 다. SqlConnection 은 그 중의 하나 입 니 다. 아래 처럼 SqlConnection 을 닫 을 수 있 습 니 다.
public void ExecuteCommand(string connString, string commandString)
{ 
	SqlConnection myConnection = null; 
	try 
	{
		myConnection = new SqlConnection(connString); 
		SqlCommand mySqlCommand = new SqlCommand
		(commandString, myConnection);
		myConnection.Open(); 
		mySqlCommand.ExecuteNonQuery();
	} 
	finally 
	{
		if (myConnection != null) 
			myConnection.Close();
	} 
}

  
       이 버 전 은 연결 을 닫 습 니 다. 하지만 재 활용 과 는 조금 다 릅 니 다. Dispose 방법 은 자원 만 방출 하 는 것 이 아 닙 니 다. 쓰레기 수 거 기 는 분석 함 수 를 실행 하지 않 아 도 된다 고 알려 줍 니 다. Dispose 는 GC. SuperpressFinalize () 를 호출 합 니 다.. Close 는 이러한 동작 이 없습니다. 결 과 는 분석 대기 열 에 있 습 니 다. 분석 이 필요 하지 않 더 라 도 선택 할 수 있다 면 Dispose 는 Close 보다 더 좋 습 니 다. 원칙 18 을 보고 모든 세부 사항 을 알 수 있 습 니 다.
 
       Dispose () 는 대상 을 메모리 에서 제거 하지 않 습 니 다. 대상 이 비 위탁 관리 자원 을 방출 하도록 촉발 합 니 다. 이 는 회수 한 대상 을 사용 하 는 데 문제 가 있 음 을 의미 합 니 다. 위의 SQLConnection 이 예 입 니 다. SQLConnection 의 Dispose ()방법 은 데이터베이스 연결 을 끊 었 습 니 다. 이 연결 을 회수 한 후에 도 SQLConnection 은 메모리 에 남아 있 지만 데이터베이스 와 연결 하지 않 습 니 다. 따라서 인 용 된 대상 을 어디에서 도 회수 하지 마 십시오.
 
       어떤 면 에 서 는 C \ # 의 자원 관리 가 C + + 보다 더 어 려 울 수 있 습 니 다. 사용 되 는 모든 자원 을 최종 분석 함수 에 의존 해 서 는 안 됩 니 다. 하지만 쓰레기 수 거 체 제 는 더 이상 간단 할 수 없습니다. 대부분의 클래스 에 사용 해도 IDisposable 을 실현 하지 못 했 습 니 다. Net 프레임 워 크 의 1500 여 개 클래스 에 서 는 100 개 이하 만 이 IDisposable 을 실현 합 니 다. 클래스 를 사용 하면,그것들 을 회수 하 는 것 을 기억 하 세 요. 이 대상 들 을 using 블록 이나 try / finally 블록 에 넣 을 수 있 습 니 다. 어떤 방식 을 사용 하 든 모든 대상 이 적당 하 게 풀 려 날 수 있 도록 하 세 요.
  
 
소결:
       D. S. Qiu 는 줄곧 Dispose 의 역할 을 모 르 고 있 으 며 Close 와 Dispose 의 차이 도 의 심 스 럽 습 니 다 (문 말 에 대한 해답, 통쾌 함). 그러나 Dispose 에 대해 서 는 제대로 알 지 못 하고 있 습 니 다. C \ # Dispose 의 내부 절 차 를 수행 하 는 것 은 어 떻 습 니까? 어떤 조작 을 했 습 니까?
  
       각종 불쾌 함 을 환영 합 니 다. 각종 스프레이, 이것 은 순 전 히 개인 적 인 취미 입 니 다. '공유' 의 덕 을 지 킵 니 다!
       이 책 에 관 한 다른 장 번역 클릭 하여 보기, 전재 출처 를 밝 히 고 오리지널 을 존중 하 세 요!
 
       D. S. Qiu 에 대한 조언 이나 의견 이 있 으 면 글 뒤에 댓 글 을 달 거나 메 일 (gd. [email protected]) 교류, 당신 의 격려 와 지 지 는 제 가 앞으로 나 아 가 는 동력 입 니 다. 더 많은 공유 가 있 기 를 바 랍 니 다.
       전재 할 때 문수 에 출처 를 밝 혀 주 십시오. http://dsqiu.iteye.com/blog/2078084
더 많은 하 이 라 이 트 는 D. S. Qiu 블 로그 와 웨 이 보 (ID: 정수 축 풍) 를 주목 해 주세요.

좋은 웹페이지 즐겨찾기