2010-02-13 5 views
4

다음 코드는 using(...) 기능/용도와 관련이 없습니까?
GC 성능이 저하 될 수 있습니까?`using (...) '을 사용하면 효과적으로 쓸모 없거나 비효율적입니까?

class Program 
{ 
    static Dictionary<string , DisposableClass> Disposables 
    { 
     get 
     { 
      if (disposables == null) 
       disposables = new Dictionary<string , DisposableClass>(); 

      return disposables; 
     } 
    } 

    static Dictionary<string , DisposableClass> disposables; 

    static void Main(string[] args) 
    { 
     DisposableClass disposable; 
     using (disposable = new DisposableClass()) 
     { 
      // do some work 
      disposable.Name = "SuperDisposable"; 
      Disposables["uniqueID" + Disposables.Count] = disposable; 
     } 

     Console.WriteLine("Output: " + Disposables["uniqueID0"].Name); 

     Console.ReadLine(); 
    } 
} 

class DisposableClass : IDisposable 
{ 
    internal string Name 
    { 
     get { return myName; } 
     set { myName = value; } 
    } 

    private string myName; 

    public void Dispose() 
    { 
     //throw new NotImplementedException(); 
    } 
} 

출력 : SuperDisposable

using(...) 기능의 나의 이해는 즉시 DisposableClass 처분을 강제하는 것입니다. 그러나 코드 블록 내에서 클래스를 사전 컬렉션에 추가합니다. 내 이해 클래스는 본질적으로 참조 형식입니다. 그래서 내 실험은 이러한 방식으로 컬렉션에 추가 된 일회용 객체에 어떤 일이 일어날지를 확인하는 것이 었습니다.

이 경우 DisposableClass은 여전히 ​​아주 오래되었습니다. 클래스는 참조 유형입니다. 따라서 컬렉션은 단순히이 유형을 참조하는 것이 아니라 실제로 클래스를 값으로 유지한다는 가정이되었습니다. 그러나, 그것도 이해가되지 않았다.

그래서 실제로 무엇이 일어나고 있습니까?

EDIT : 일부 답변에서 제안한 것처럼 객체가 죽지 않았 음을 증명하는 출력 코드가 수정되었습니다.

2 편집 :이 아래로 좀 더 많은 코드를 통해 갔어요로 제공이 무엇 : 코드를 통해 스테핑

public void Dispose() 
    { 
     Dispose(true); 
     GC.SuppressFinalize(this); 
    } 

    private void Dispose(bool dispose) 
    { 
     if (!isDisposed) 
     { 
      if (dispose) 
      { 
       // clean up managed objects 
      } 

      // clean up unmanaged objects 
      isDisposed = true; 
     } 
    } 

    ~DisposableClass() 
    { Dispose(false); } 

방법에 전달됩니다 false (private void Dispose(bool dispose)에서 중단 점을했다) , 여기에 자원이 적절히 처분되어야합니다. 그럼에도 불구하고 수업은 아직 살아 있지만 예외적으로 스스로를 설정하고 있습니다. 대답이 나를 호기심에 떨게했습니다 ...

답변

11

개체를 삭제해도 파괴되지 않습니다. 더 이상 필요하지 않은 관리되지 않는 리소스를 정리하도록 지시합니다. 예를 들어, 일회용 객체를 만들고, 사전에 할당 한 다음, 일부 리소스를 제거하라고 지시하는 것입니다.

using 문에 대한 올바른 시나리오는 리소스를 초기화하고 그 리소스로 무언가를 수행 한 다음이를 삭제하고 잊어 버리는 경우입니다. 예를 들면 :

using (var stream = new FileStream("some-file.txt")) 
using (var reader = new StreamReader(stream)) 
{ 
    Console.Write(reader.ReadToEnd()); 
} 

당신이 그것을 사용 한 후에 개체를 유지하려면

, 당신은 그것을 폐기해서는 안되며 그러므로 using 문은 사용할 수 없습니다.

+0

충분합니다. 나는 무슨 일이 일어나고 있는지 이해하려고 애썼다. 오브젝트가 처리 중이거나 해당 오브젝트와 연관된 자원 인 경우 +1 – IAbstract

2

블록이 완료된 후에 개체가 필요하므로이 경우 using 블록을 사용하면 안됩니다. 이것은 객체의 수명의 명확한 시작 및 끝 점이있을 때만 사용됩니다.

1

IDisposable 인터페이스는 유형이 어떤 종류의 자원을 관리한다는 것을 나타냅니다. Dispose 메서드는 가비지 수집이 수행 될 때까지 대기하지 않고 인스턴스가 사용하는 리소스를 처리하고 finalizer가 리소스를 해제 할 수있게합니다.

예를 들어, 사전에는 여전히 일회용 클래스에 대한 참조가 포함되어 있지만이 인스턴스는 using 블록의 끝에 배치되었습니다. 인스턴스의 메소드를 호출하려는 후속 시도는 이제 ObjectDisposedException 또는 InvalidOperationException을 던져 인스턴스가 더 이상 "작동 중"상태가 아님을 나타냅니다.

IDisposable을 삭제하는 것은 인스턴스가 차지한 메모리를 해제하거나 인스턴스에서 가비지 수집 루틴을 호출하는 것과 혼동되어서는 안됩니다. 인스턴스는 가비지 컬렉터가 다른 인스턴스와 마찬가지로 추적 및 관리하며 가비지 수집자가이를 결정할 때만 릴리스됩니다.

+0

@ 프로그래밍 영웅 : 두 번째 단락은 부분적으로 정확합니다 ... 자원의 적절한 처리와 모든 반원들이 그 폐기 된 자원에 접근하는지 여부에 달려 있습니다. 그것은 여전히 ​​이상한 행동처럼 보입니다. 그것을 편집하면 아래쪽 투표를 제거합니다. ;) – IAbstract

+0

배치 된 인스턴스의 동작은 크게 정의되지 않습니다. 인스턴스가 폐기 될 때 인스턴스가 더 이상 정상적으로 작동하지 않을 것이라고 가정하는 것이 기대됩니다. 일부 속성은 여전히 ​​정상적으로 값을 반환하지만 대부분의 메서드는 실패 할 것으로 예상됩니다. –

2

약간 특별한 인터페이스인데도 불구하고 IDisposable은 인터페이스라는 점을 기억해야합니다. using 블록이 종료되면 개체의 Dispose()를 호출합니다. 아무것도 더. 참조가 유효하며 Dispose 메서드가 아무 작업도 수행하지 않으면 개체에 전혀 영향을주지 않습니다. 처리를 추적하지 않고 명시 적으로 예외를 throw하지 않으면 .NET에 고유하게 처리 된 상태가 없으므로이 시점 이후에도 예외가 발생하지 않습니다.

+0

+1 @ 닉 : 'IDispose'에 대한 좋은 지적. – IAbstract

관련 문제