2010-07-07 3 views
3

나는 읽었으며 C#의 using 문이하는 것을 이해한다고 생각한다. (내가 틀렸다면 나를 교정 해주십시오.) IDisposable 객체를 제한된 범위 (using 블록)로 읽기 전용으로 초기화합니다. 난 당신이 using 전에 초기화 할 수 있으며, 그 범위를 제한하지 않습니다 알고 있지만, 여기서는 그 방법에 대해 좋습니다 : 난 항상 클래스가 무엇의 서브 클래스 무엇에주의를 지불하고 있지 않다C#에서 사용하는 클래스는 무엇입니까?

http://msdn.microsoft.com/en-us/library/yh598w02.aspx

. 나는 IDisposable로부터 상속받은 클래스가 무엇인지 확실하지 않습니다. 어떤 클래스가 using 문에서 사용될 수 있는지 궁금하지 않고, 동료가 using 블록에서 어떤 클래스를 찾으려고합니까? 클래스는 블록이 using 블록에 있어야합니까? 또한, 블록을 사용하지 않고 using 블록을 사용하고 Dispose를 호출하지 않는다면 실제로 문제가 있습니까? 그것은 단지 기억이나 안정성에 관한 것입니까?

+0

부분적인 대답은 http://stackoverflow.com/questions/2988321/how-to-find-all-classes-implemeting-idisposable을 참조하십시오. – apoorv020

답변

16

엄밀히 말하면, IDisposable을 구현하고 범위가 해당 기능으로 제한되는 모든 객체는 using 블록 내에 있어야합니다. IDisposable 인터페이스는 관리되지 않는 리소스 (데이터베이스 연결, 파일 핸들, 창 핸들 등)를 처리하는 클래스가 이러한 리소스를 적시에 결정적으로 처리 할 수 ​​있도록합니다. 있다

, 일반적으로 세 가지 방법은에서 IDisposable 객체는 클래스 내에서 사용됩니다

  1. 목적은 모두 만들어 더 이상 하나의 메소드 호출의 범위 내에서 필요하다. 이것은 매우 일반적이며, using을 사용할 수 있고 사용할 수 있어야합니다.
  2. 개체는 클래스에 의해 만들어지며 (또는 클래스에 전달됩니다.) 개체의 수명은 단일 메서드 호출의 범위를 넘어 확장되지만 해당 클래스의 수명을 초과하지 않습니다. 예를 들어, 클래스는 Stream을 만들고 그 객체의 수명 동안 사용해야합니다. 이 경우 클래스는 IDisposable 자체를 구현하고 자신의 Dispose 메서드가 호출 될 때 소유하고있는 객체를 처리해야합니다. 예를 들면 다음과 같습니다. System.IO.StreamWriter
  3. 개체가 클래스에 전달되었지만 클래스가 해당 개체를 "소유"하지 않습니다. 즉, IDisposable 개체의 사용 가능한 수명은 단일 메서드 호출의 범위를 벗어나며 개체 수명보다 길 수 있습니다. 이 경우 다른 사람이 Dispose에게 전화해야합니다.

첫 번째 경우가 가장 자주 발생하며, 이는 using 블록이 존재하는 이유입니다. 예외가 발생한 경우에도 객체가 처리되도록 보장합니다.

몇 가지 예 :

  • 스트림 클래스
  • 데이터베이스 연결/명령
  • 제어

IDisposable를 구현하는 클래스의 더 완전한 목록은이 목록이 상당히 큰 것 같이 없습니다 및 당신은 결코 만날 수없는 수업으로 가득 차 있습니다. 클래스 이 어떤 일을하는지 생각해보십시오.; 어떤 종류의 연결이나 파일을 열어야합니까? 일반적으로 은 어떤 종류의 리소스를 확보해야합니까?? 그렇다면, 아마 그것을 구현합니다. 기본 레벨에서 컴파일러가 using으로 묶을 수있게하면 IDisposable을 구현합니다.

의 결과에 대해서는이 아니고, Dispose으로 전화하는 것은 고려하지 마십시오. 통화 처분. 사실, 방어적인 표준은 관리되지 않는 리소스 을 직접 사용하여을 사용하는 경우 객체를 수집하고 다른 사람이 호출하지 못했지만 디자인이 아니어야하는 경우 dispose를 호출하는 finalizer를 정의해야합니다. 선택. 나는 지금까지 알고있다. 클래스의 준비 계산하는 사람이 using와 전화

+1

+1 : 좋은 답변입니다. –

+1

항상 처분을 호출 하시겠습니까? 'IDisposable'이 아무것도 정리하지 못한다면, 나는 항상 콘크리트를 다루고 있다는 것을 안다. (여기서'SqlCommand'와 같은 것을 생각해 보라). – Marc

+1

@Marc : 클래스가'IDisposable'을 구현하면, 이유가 있습니다.'SqlCommand'의 특정 구현 인'Dispose (bool)'은 벌거로 보일 수 있지만 다른 명령 클래스에서 스와핑하는 경우에는 동일하지 않을 수 있습니다. 권장 지침을 따르면 * 아무것도 잃지 않을 수 있습니다. 그리고 단점은 당신이 일관성이 있으며, 사람들이 당신의 물건을 적절하게 폐기하지 않는다는 사실을 지적하고 비웃을 필요가 없다는 것입니다. –

1

적어도 관리되지 않는 리소스를 사용하는 모든 클래스

13

메모리와 관련이 없습니다. 파일 핸들, 데이터베이스 연결 등과 같은 다른 리소스에 대한 것입니다.

기본적으로 클래스가 IDisposable을 구현하는 경우 비용이 많이 드는 관리되지 않는 리소스가있을 수 있기 때문에 완료 할 때 처분해야한다는 신호입니다. 주위를 떠나십시오. (예 : 연결 풀의 연결이 끊어 지거나 파일 핸들이 열려있어 다른 파일이 동일한 파일을 다시 열지 못하게합니다.)

+0

클래스가 Idisposable을 구현하면 어떻게됩니까? 그들은 "특별한"소멸자를 받았습니까? GC가 그들을 빨리 청소합니까? 등 등? 내가 수업을 가지고 있고, 파일을 열거 나 닫을 때 사용할 수 있습니다. idisposable 구현은 나를 위해 무엇을 할 것인가? 죄송합니다. 여기 학생 : P – masfenix

+0

@maxfenix : 별도의 질문으로 질문 할 수 있습니다. (페이지 상단의 "질문하기"를 클릭하십시오.) –

+3

@masfenix : 곧 * 아무것도 쓰지 마십시오 *. 'IDisposable'은 ** 단지 다른 인터페이스 **입니다.이 특수 언어를 직접 다루는 특수 언어 요소 ('using' 블록)가 있다는 점에서 특별합니다. 인터페이스를 구현하는 방법 *에 대해 제안 된 디자인 패턴이 있지만 실제로는 특별한 것이 없습니다. GC는 직접적으로 아무것도하지 않습니다. –

1

사용 블록을 사용하지 않고 Dispose를 호출하지 않으면 메모리 및/또는 리소스가 누출 될 가능성이 큽니다. using은 편리하지만 실제로 IDisposable에서 파생되는 모든 객체에서 Dispose를 호출해야합니다.

+3

그리고 finally {} 블록에서 수행하십시오 –

+1

실제로 사용 블록에서 오류가 발생하면 dispose가 자동으로 호출되며 finally 블록에서 호출 할 필요가 없습니다. 질문에 포함 된 링크를 확인하십시오. –

0

블록을 사용중인 클래스를 사용하는 것에 대해 걱정할 필요가 없습니다. 당신이 성명서를 사용하여 사용하지 않았다면 doesnot은 IDisposbale을 구현합니다. 그러면 빨간색/파란색 물결이 표시됩니다. 그래서 당신은 그것의 결여 된 인터페이스가 없다는 것을 알 수 있습니다. 그리고 지금까지 거의 모든 클래스의 프레임 워크를 사용하여 Idisposable을 구현했습니다. 하지만 사용자 정의 클래스에서 구현해야합니다

+0

내가 틀렸어. 설명해 주 시겠어요? –

+2

나는 투표가 안 좋았지 만, 그 대답이 프레임 워크 클래스를 폐기 할 때 게으름을 조장 할 수 있기 때문이라고 생각합니다. 그들이 일회용 패턴을 구현한다고해서 그것이 완료되었을 때 처분하지 않는 것이 좋습니다. – Tesserex

+0

try-catch하고 처리하는 모든 것을 사용합니다. 내가 맞다면 –

1

일회용 클래스 인 경우 인텔리 센스를 직접 조사하거나 경험을 통해 배울 수 있습니다. 일반적으로 Image 및 해당 하위 항목이 포함되며 실제로는 System.Drawing 네임 스페이스, 많은 파일 스트림, 데이터베이스 연결 등이 포함됩니다.

가능한 한 빨리 호출해야합니다. 일회용이라는 것을 알고 있고 그 일을 처리했다는 것을 알고 있다면 Dispose로 전화하십시오.

IDisposable을 구현하는 많은 .NET 기본 클래스는 일회용 패턴을 구현합니다. 즉 가비지 수집기가 가져 오는 패턴을 제대로 처리 할 수 ​​있다는 것을 의미합니다. 그러나 그렇다고하더라도,

  1. 당신은 참조 주위를 어슬렁 (누수)을 남길 수 있기 때문에 당신은 아직도 당신이 완료 일을 처리해야하며 배치되지 않습니다, 또는
  2. GC의는 할 수 없습니다 잠시 와봐.

또한 자신이 작성한 수업의 경우 가비지 수집은 관리되지 않는 리소스에 대한 적절한 처리와 동일하지 않습니다. 이는 흔히 혼란입니다. 일회용 패턴은 직접 구현해야합니다.

1

클래스가 IDisposable을 구현하는 주된 이유는 관리되지 않는 리소스를 해제하는 것입니다. 가비지 콜렉터는 관리 자원이 범위를 벗어나 적합하다고 판단 할 때 관리 자원을 해제하지만 관리되지 않는 자원은 알지 못합니다. Dispose 메서드를 호출하면 명시 적으로 리소스가 해제됩니다.

using 블록을 사용하지 않거나 Dispose 메서드를 호출하면 메모리 누수 문제가 발생하여 안정성 문제가 발생할 수 있습니다.

IDisposable을 구현하는 클래스를 다룰 때는 항상 using 블록을 사용해야합니다. Try.. Catch.. Finally을 선호하여 finally 블록에서 Dispose으로 전화하면 예외를 처리 할 수 ​​있습니다.

2

당신이해야 항상IDisposable을 구현하고이 가장 쉽게 using 블록을 통해 이루어집니다 모든 클래스에 전화 Dispose.

이것은 단지 메모리에 관한 것이 아닙니다. 이것은 또한 자원에 관한 것이 아닙니다. 이것은 정확성에 관한 것입니다.

StreamWriter이 대표적인 예입니다. Microsoft는 an MDA을 개발하여 프로그래머가 Dispose에 전화하는 것을 잊어 버린 경우를 포착했습니다. 이것은 단지 메모리 또는 리소스 이상입니다. StreamWriter 예에서 쓰여지는 파일은 잘릴 수 있습니다.

나는 데이터베이스 트랜잭션이 롤백되고있는 한 번 더 심한 버그 (실제로 내 보스 코드에서)를 추적해야했습니다 ... 원인이 밝혀졌습니다. Dispose은 호출되지 않았으므로 프로세스가 종료 될 때 디스크에 너무 많이 커밋하려고했습니다 (프로세스 종료 중 종료 자에 대한 시간 초과가 있습니다). 수정 사항은 몇 가지 using 블록이었습니다.

세 번째 예 : Microsoft의 관리 ESENT 래퍼 클래스가 Dispose가 올바른 순서 (마지막 "외부"클래스)에서 호출 할 필요 "3 개 계층"처분 방식이있다.

실제 사례가 이고 Dispose이 제대로 호출되지 않으면이 작동하지 않을 수 있습니다. 다른 클래스도 비슷한 동작을 나타낼 수 있습니다.

일반적으로 은 항상으로 전화해야합니다. Dispose으로 전화하십시오.

0

은 다음과 같습니다

  • 스트림
  • 데이터베이스 연결, 명령 및 데이터 판독기
  • 독자와 작가를

있습니다 많은 많은 또한 Dispose해야하는 클래스가 있지만 위의 클래스는 자주 사용되며 좁은 사용 범위에서 자주 사용됩니다.

예 - using을 사용하지 않고 dispose을 호출하지 않는 문제가 있습니다. 고전은 데이터베이스에 대한 연결을 닫지 않고 효과적으로 연결을 유지하면서 데이터베이스 서버에서 리소스를 빠져 나가는 웹 응용 프로그램입니다.

1

IDisposable의 목적은 관리되지 않는 리소스 (파일, 데이터베이스 또는 그래픽 컨텍스트와 같은)와 상호 작용하는 개체가 자체적으로 정리할 수있게하는 것입니다. 사용하는 문은 과정의 문제는 IDisposable을 구현하는 오브젝트를 아는 것입니다

var disposable = new MemoryStream(); 
try 
{ 
    //do some work with the disposable object 
} 
finally 
{ 
    if (disposable!=null) 
    disposable.Dispose(); 
} 

를 구성하는 다음과 같은 ... 불행하게도 워드 프로세서 외에 알 수있는 자동화 된 방법이없는 편리한 속기이다. 비록 내가 사용하는 IDisposables를 확인하는 Fxcop 설정이 있다고 생각합니다.

관련 문제