IDisposable을 구현하는 개체 사용Using objects that implement IDisposable

공용 언어 런타임의 가비지 수집기는 관리되는 개체에서 사용하는 메모리를 회수하지만, 관리되지 않는 리소스를 사용하는 유형에서는 관리되지 않는 이러한 리소스에 할당된 메모리를 회수할 수 있게 하는 IDisposable 인터페이스를 구현합니다.The common language runtime's garbage collector reclaims the memory used by managed objects, but types that use unmanaged resources implement the IDisposable interface to allow the memory allocated to these unmanaged resources to be reclaimed. IDisposable을 구현하는 개체의 사용을 마치면 해당 개체의 IDisposable.Dispose 구현을 호출해야 합니다.When you finish using an object that implements IDisposable, you should call the object's IDisposable.Dispose implementation. 이 작업은 다음 두 가지 방법 중 하나로 수행할 수 있습니다.You can do this in one of two ways:

  • C# using 문 또는 Visual Basic Using 문 사용With the C# using statement or the Visual Basic Using statement.

  • try/finally 블록 구현By implementing a try/finally block.

using 문The using statement

C#의 using 문과 Visual Basic의 Using 문은 개체를 만들고 정리하기 위해 작성해야 하는 코드를 단순화합니다.The using statement in C# and the Using statement in Visual Basic simplify the code that you must write to create and clean up an object. using 문은 하나 이상의 리소스를 가져와서, 사용자가 지정하는 문을 실행한 다음, 개체를 자동으로 삭제합니다.The using statement obtains one or more resources, executes the statements that you specify, and automatically disposes of the object. 그러나 using 문은 개체가 생성된 메서드의 범위 내에서 사용되는 개체에만 유용합니다.However, the using statement is useful only for objects that are used within the scope of the method in which they are constructed.

다음 예제에서는 using 문을 사용하여 System.IO.StreamReader 개체를 만들고 해제합니다.The following example uses the using statement to create and release a System.IO.StreamReader object.

using System;
using System.IO;

public class Example
{
   public static void Main()
   {
      Char[] buffer = new Char[50];
      using (StreamReader s = new StreamReader("File1.txt")) {
         int charsRead = 0;
         while (s.Peek() != -1) {
            charsRead = s.Read(buffer, 0, buffer.Length);
            //
            // Process characters read.
            //   
         }
      }

   }
}
Imports System.IO

Module Example
   Public Sub Main()
      Dim buffer(49) As Char
      Using s As New StreamReader("File1.txt")
         Dim charsRead As Integer
         Do While s.Peek() <> -1
            charsRead = s.Read(buffer, 0, buffer.Length)         
            ' 
            ' Process characters read.
            '
         Loop
      End Using
   End Sub
End Module

StreamReader 클래스가 IDisposable 인터페이스를 구현하며, 이는 관리되지 않는 리소스를 사용함을 나타내지만 예제에서는 StreamReader.Dispose 메서드를 명시적으로 호출하지 않습니다.Note that although the StreamReader class implements the IDisposable interface, which indicates that it uses an unmanaged resource, the example doesn't explicitly call the StreamReader.Dispose method. C# 또는 Visual Basic 컴파일러가 using 문을 발견하면 try/finally 블록을 명시적으로 포함하는 다음 코드와 동일한 중간 언어(IL)를 표시합니다.When the C# or Visual Basic compiler encounters the using statement, it emits intermediate language (IL) that is equivalent to the following code that explicitly contains a try/finally block.

using System;
using System.IO;

public class Example
{
   public static void Main()
   {
      Char[] buffer = new Char[50];
      {
         StreamReader s = new StreamReader("File1.txt"); 
         try {
            int charsRead = 0;
            while (s.Peek() != -1) {
               charsRead = s.Read(buffer, 0, buffer.Length);
               //
               // Process characters read.
               //   
            }
         }
         finally {
            if (s != null)
               ((IDisposable)s).Dispose();     
         }       
      }
   }
}
Imports System.IO

Module Example
   Public Sub Main()
      Dim buffer(49) As Char
''      Dim s As New StreamReader("File1.txt")
With s As New StreamReader("File1.txt")
      Try
         Dim charsRead As Integer
         Do While s.Peek() <> -1
            charsRead = s.Read(buffer, 0, buffer.Length)         
            ' 
            ' Process characters read.
            '
         Loop
      Finally
         If s IsNot Nothing Then DirectCast(s, IDisposable).Dispose()
      End Try
End With
   End Sub
End Module

또한 C# using 문을 사용하면 단일 문으로 여러 리소스를 가져올 수 있으며, 이는 중첩된 using 문의 기능과 내부적으로 동일합니다.The C# using statement also allows you to acquire multiple resources in a single statement, which is internally equivalent to nested using statements. 다음 예제에서는 서로 다른 두 파일의 내용을 읽을 수 있도록 두 개의 StreamReader 개체를 인스턴스화합니다.The following example instantiates two StreamReader objects to read the contents of two different files.

using System;
using System.IO;

public class Example
{
   public static void Main()
   {
      Char[] buffer1 = new Char[50], buffer2 = new Char[50];
      
      using (StreamReader version1 = new StreamReader("file1.txt"),
                          version2 = new StreamReader("file2.txt")) {
         int charsRead1, charsRead2 = 0;
         while (version1.Peek() != -1 && version2.Peek() != -1) {
            charsRead1 = version1.Read(buffer1, 0, buffer1.Length);
            charsRead2 = version2.Read(buffer2, 0, buffer2.Length);
            //
            // Process characters read.
            //
         }
      }
   }
}

Try/finally 블록Try/finally block

using 문에서 try/finally 블록을 래핑하는 대신 try/finally 블록을 직접 구현하도록 선택할 수 있습니다.Instead of wrapping a try/finally block in a using statement, you may choose to implement the try/finally block directly. 개인적인 코딩 스타일에 따라서 또는 다음 이유 중 하나로 인해 이를 수행할 수 있습니다.This may be your personal coding style, or you might want to do this for one of the following reasons:

  • catch 블록에서 throw된 모든 예외를 처리하기 위해 try 블록을 포함하려는 경우To include a catch block to handle any exceptions thrown in the try block. 그렇지 않으면, using 문에서 throw된 예외가 try/catch 블록이 없는 경우 using 블록 내에 throw되는 예외와 마찬가지로 처리됩니다.Otherwise, any exceptions thrown by the using statement are unhandled, as are any exceptions thrown within the using block if a try/catch block isn't present.

  • 범위가 선언된 범위 내의 블록에 대해 로컬이 아닌 IDisposable을 구현하는 개체를 인스턴스화하려는 경우To instantiate an object that implements IDisposable whose scope is not local to the block within which it is declared.

try/catch/finally 블록을 사용하여 StreamReader 개체를 인스턴스화, 사용 및 삭제하고 StreamReader 생성자 및 해당 ReadToEnd 메서드에서 throw된 예외를 처리한다는 점을 제외하면 다음 예제는 이전 예제와 유사합니다.The following example is similar to the previous example, except that it uses a try/catch/finally block to instantiate, use, and dispose of a StreamReader object, and to handle any exceptions thrown by the StreamReader constructor and its ReadToEnd method. finally 블록의 코드가 IDisposable 메서드를 호출하기 전에 null을 구현하는 개체가 Dispose이 아닌지 확인합니다.Note that the code in the finally block checks that the object that implements IDisposable isn't null before it calls the Dispose method. 이렇게 하지 않으면 런타임에 NullReferenceException 예외가 발생할 수 있습니다.Failure to do this can result in a NullReferenceException exception at run time.

using System;
using System.Globalization;
using System.IO;

public class Example
{
   public static void Main()
   {
      StreamReader sr = null;
      try {
         sr = new StreamReader("file1.txt");
         String contents = sr.ReadToEnd();
         Console.WriteLine("The file has {0} text elements.", 
                           new StringInfo(contents).LengthInTextElements);    
      }      
      catch (FileNotFoundException) {
         Console.WriteLine("The file cannot be found.");
      }   
      catch (IOException) {
         Console.WriteLine("An I/O error has occurred.");
      }
      catch (OutOfMemoryException) {
         Console.WriteLine("There is insufficient memory to read the file.");   
      }
      finally {
         if (sr != null) sr.Dispose();     
      }
   }
}
Imports System.Globalization
Imports System.IO

Module Example
   Public Sub Main()
      Dim sr As StreamReader = Nothing
      Try 
         sr = New StreamReader("file1.txt")
         Dim contents As String = sr.ReadToEnd()
         Console.WriteLine("The file has {0} text elements.", 
                           New StringInfo(contents).LengthInTextElements)    
      Catch e As FileNotFoundException
         Console.WriteLine("The file cannot be found.")
      Catch e As IOException
         Console.WriteLine("An I/O error has occurred.")
      Catch e As OutOfMemoryException
         Console.WriteLine("There is insufficient memory to read the file.")   
      Finally 
         If sr IsNot Nothing Then sr.Dispose()     
      End Try
   End Sub
End Module

프로그래밍 언어가 using 문을 지원하지 않지만, Dispose 메서드에 대한 직접 호출을 허용하므로 try/finally 블록을 구현하도록 선택하거나 구현해야 하는 경우 이 기본 패턴을 따를 수 있습니다.You can follow this basic pattern if you choose to implement or must implement a try/finally block, because your programming language doesn't support a using statement but does allow direct calls to the Dispose method.

참고 항목See also