System.IDisposable 인터페이스
이 문서에서는 이 API에 대한 참조 설명서에 대한 추가 설명서를 제공합니다.
인터페이스의 IDisposable 기본 사용은 관리되지 않는 리소스를 해제하는 것입니다. 가비지 수집기는 해당 개체가 더 이상 사용되지 않을 때 관리되는 개체에 할당된 메모리를 자동으로 해제합니다. 그러나 가비지 수집이 발생할 시기를 예측할 수 없습니다. 또한 가비지 수집기는 창 핸들 또는 열린 파일 및 스트림과 같은 관리되지 않는 리소스에 대해 전혀 알지 않습니다.
이 인터페이스의 메서드를 Dispose 사용하여 가비지 수집기와 함께 관리되지 않는 리소스를 명시적으로 해제합니다. 개체가 더 이상 필요하지 않은 경우 개체 소비자가 이 메서드를 호출할 수 있습니다.
Warning
기존 클래스에 인터페이스를 추가하는 IDisposable 것은 호환성이 손상되는 변경입니다. 형식의 기존 소비자는 호출 Dispose할 수 없으므로 형식에서 보유하는 관리되지 않는 리소스가 릴리스될 것이라고 확신할 수 없습니다.
IDisposable.Dispose 인스턴스가 소유한 리소스가 더 이상 필요하지 않은 경우 형식의 소비자가 구현을 호출하기 때문에 관리되는 개체 SafeHandle 를 래핑하거나(권장되는 대안) 소비자가 호출Dispose을 잊어버린 경우 관리되지 않는 리소스를 해제하도록 재정 Object.Finalize 의해야 합니다.
Important
.NET Framework에서 C++ 컴파일러는 리소스의 결정적 삭제를 지원하며 메서드의 직접 구현을 Dispose 허용하지 않습니다.
이 인터페이스와 Object.Finalize 메서드를 사용하는 방법에 대한 자세한 내용은 가비지 수집 및 Dispose 메서드 구현 항목을 참조하세요.
IDisposable을 구현하는 개체 사용
앱에서 인터페이스를 구현 IDisposable 하는 개체만 사용하는 경우 사용이 완료되면 개체의 IDisposable.Dispose 구현을 호출해야 합니다. 프로그래밍 언어에 따라 다음 두 가지 방법 중 하나로 이 작업을 수행할 수 있습니다.
- C# 및 Visual Basic의
using
문과 같은 언어 구문과 F#의use
문 또는using
함수를 사용합니다. - 블록에서 구현
try
/finally
에 대한 호출을 IDisposable.Dispose 래핑합니다.
참고 항목
구현 IDisposable 하는 형식에 대한 설명서는 해당 사실을 확인하고 해당 구현을 호출 Dispose 하기 위한 미리 알림을 포함합니다.
C#, F#, Visual Basic Using 문
언어가 C#의 using 문, Visual Basic의 Using 문 또는 F#의 use 문과 같은 구문을 지원하는 경우 명시적으로 자신을 호출 IDisposable.Dispose 하는 대신 사용할 수 있습니다. 다음 예제에서는 파일에 대한 정보와 파일의 단어 수를 유지하는 클래스를 정의하는 WordCount
데 이 방법을 사용합니다.
using System;
using System.IO;
using System.Text.RegularExpressions;
public class WordCount
{
private String filename = String.Empty;
private int nWords = 0;
private String pattern = @"\b\w+\b";
public WordCount(string filename)
{
if (!File.Exists(filename))
throw new FileNotFoundException("The file does not exist.");
this.filename = filename;
string txt = String.Empty;
using (StreamReader sr = new StreamReader(filename))
{
txt = sr.ReadToEnd();
}
nWords = Regex.Matches(txt, pattern).Count;
}
public string FullName
{ get { return filename; } }
public string Name
{ get { return Path.GetFileName(filename); } }
public int Count
{ get { return nWords; } }
}
open System.IO
open System.Text.RegularExpressions
type WordCount(filename) =
let txt =
if File.Exists filename |> not then
raise (FileNotFoundException "The file does not exist.")
use sr = new StreamReader(filename)
sr.ReadToEnd()
let pattern = @"\b\w+\b"
let nWords = Regex.Matches(txt, pattern).Count
member _.FullName = filename
member _.Name = Path.GetFileName filename
member _.Count = nWords
Imports System.IO
Imports System.Text.RegularExpressions
Public Class WordCount
Private filename As String
Private nWords As Integer
Private pattern As String = "\b\w+\b"
Public Sub New(filename As String)
If Not File.Exists(filename) Then
Throw New FileNotFoundException("The file does not exist.")
End If
Me.filename = filename
Dim txt As String = String.Empty
Using sr As New StreamReader(filename)
txt = sr.ReadToEnd()
End Using
nWords = Regex.Matches(txt, pattern).Count
End Sub
Public ReadOnly Property FullName As String
Get
Return filename
End Get
End Property
Public ReadOnly Property Name As String
Get
Return Path.GetFileName(filename)
End Get
End Property
Public ReadOnly Property Count As Integer
Get
Return nWords
End Get
End Property
End Class
using
문(use
F#의 식)은 실제로 구문 편의성입니다. 컴파일 시 언어 컴파일러는 블록에 대한 IL(중간 언어)을 try
/finally
구현합니다.
문에 대한 using
자세한 내용은 Using 문 또는 using Statement 항목을 참조하세요.
Try/Finally 블록
프로그래밍 언어가 C# 또는 Visual Basic의 문이나 F#의 문과 같은 구문을 지원하지 않거나 사용하지 않으려는 경우 문 블록try
finally
/에서 finally
구현을 호출 IDisposable.Dispose 할 수 있습니다.using
use
다음 예제에서는 이전 예제의 using
블록을 블록으로 try
/finally
바꿉니다.
using System;
using System.IO;
using System.Text.RegularExpressions;
public class WordCount2
{
private String filename = String.Empty;
private int nWords = 0;
private String pattern = @"\b\w+\b";
public WordCount2(string filename)
{
if (!File.Exists(filename))
throw new FileNotFoundException("The file does not exist.");
this.filename = filename;
string txt = String.Empty;
StreamReader? sr = null;
try
{
sr = new StreamReader(filename);
txt = sr.ReadToEnd();
}
finally
{
if (sr != null) sr.Dispose();
}
nWords = Regex.Matches(txt, pattern).Count;
}
public string FullName
{ get { return filename; } }
public string Name
{ get { return Path.GetFileName(filename); } }
public int Count
{ get { return nWords; } }
}
open System.IO
open System.Text.RegularExpressions
type WordCount2(filename) =
let txt =
if File.Exists filename |> not then
raise (FileNotFoundException "The file does not exist.")
let sr = new StreamReader(filename)
try
sr.ReadToEnd()
finally
sr.Dispose()
let pattern = @"\b\w+\b"
let nWords = Regex.Matches(txt, pattern).Count
member _.FullName = filename
member _.Name = Path.GetFileName filename
member _.Count = nWords
Imports System.IO
Imports System.Text.RegularExpressions
Public Class WordCount2
Private filename As String
Private nWords As Integer
Private pattern As String = "\b\w+\b"
Public Sub New(filename As String)
If Not File.Exists(filename) Then
Throw New FileNotFoundException("The file does not exist.")
End If
Me.filename = filename
Dim txt As String = String.Empty
Dim sr As StreamReader = Nothing
Try
sr = New StreamReader(filename)
txt = sr.ReadToEnd()
Finally
If sr IsNot Nothing Then sr.Dispose()
End Try
nWords = Regex.Matches(txt, pattern).Count
End Sub
Public ReadOnly Property FullName As String
Get
Return filename
End Get
End Property
Public ReadOnly Property Name As String
Get
Return Path.GetFileName(filename)
End Get
End Property
Public ReadOnly Property Count As Integer
Get
Return nWords
End Get
End Property
End Class
패턴에 대한finally
try
/자세한 내용은 Try... 잡을... 마지막으로 문, try-finally, try... finally Expression 또는 try-finally 문입니다.
IDisposable 구현
형식이 관리되지 않는 리소스를 직접 사용하거나 삭제 가능한 리소스를 직접 사용하려는 경우 구현 IDisposable 해야 합니다. 형식의 소비자는 인스턴스가 더 이상 필요하지 않을 때 구현을 호출 IDisposable.Dispose 하여 리소스를 해제할 수 있습니다. 호출 Dispose에 실패한 경우를 처리하려면 관리되지 않는 리소스를 래핑하기 위해 파생된 SafeHandle 클래스를 사용하거나 참조 형식에 대한 메서드를 재정의 Object.Finalize 해야 합니다. 두 경우 모두 관리되지 않는 리소스를 사용하거나, 해제하거나, 관리되지 않는 리소스를 다시 설정하는 등 관리되지 않는 리소스를 사용한 후 필요한 모든 클린를 수행하는 데 이 메서드를 사용합니다Dispose. 구현에 IDisposable.Dispose대한 자세한 내용은 Dispose(bool) 메서드 오버로드를 참조하세요.
Important
관리되지 않는 리소스를 사용하고 삭제해야 하는 서브클래스가 있거나 있을 가능성이 있는 기본 클래스를 정의하는 경우 다음 섹션에서 설명한 대로 메서드를 구현 IDisposable.Dispose 하고 두 번째 오버로드 Dispose
를 제공해야 합니다.
IDisposable 및 상속 계층 구조
삭제 가능해야 하는 서브클래스가 있는 기본 클래스는 다음과 같이 구현 IDisposable 해야 합니다. Visual Basic에서는 그렇지 않은 sealed
NotInheritable
형식에서 구현 IDisposable 할 때마다 이 패턴을 사용해야 합니다.
- 하나의 공용, 비 가상 Dispose() 메서드 및 보호된 가상
Dispose(Boolean disposing)
메서드를 제공해야 합니다. - 메서드는 Dispose() 호출
Dispose(true)
해야 하며 성능에 대한 종료를 표시하지 않아야 합니다. - 기본 형식에는 종료자가 포함되지 않아야 합니다.
다음 코드 조각은 기본 클래스에 대한 삭제 패턴을 반영합니다. 형식이 메서드를 재정의하지 않는다고 가정합니다 Object.Finalize .
using System;
using System.IO;
using System.Runtime.InteropServices;
class BaseClass1 : IDisposable
{
// Flag: Has Dispose already been called?
bool disposed = false;
// Instantiate a FileStream instance.
FileStream fs = new FileStream("test.txt", FileMode.OpenOrCreate);
// Public implementation of Dispose pattern callable by consumers.
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
// Protected implementation of Dispose pattern.
protected virtual void Dispose(bool disposing)
{
if (disposed)
return;
if (disposing)
{
fs.Dispose();
// Free any other managed objects here.
//
}
disposed = true;
}
}
open System
open System.IO
type BaseClass1() =
// Flag: Has Dispose already been called?
let mutable disposed = false
// Instantiate a FileStream instance.
let fs = new FileStream("test.txt", FileMode.OpenOrCreate)
interface IDisposable with
// Public implementation of Dispose pattern callable by consumers.
member this.Dispose() =
this.Dispose true
GC.SuppressFinalize this
// Implementation of Dispose pattern.
abstract Dispose: bool -> unit
override _.Dispose(disposing) =
if not disposed then
if disposing then
fs.Dispose()
// Free any other managed objects here.
disposed <- true
Imports System.IO
Imports System.Runtime.InteropServices
Class BaseClass1 : Implements IDisposable
' Flag: Has Dispose already been called?
Dim disposed As Boolean = False
' Instantiate a FileStream instance.
Dim fs As FileStream = New FileStream("test.txt", FileMode.OpenOrCreate)
' Public implementation of Dispose pattern callable by consumers.
Public Sub Dispose() _
Implements IDisposable.Dispose
Dispose(disposing:=True)
GC.SuppressFinalize(Me)
End Sub
' Protected implementation of Dispose pattern.
Protected Overridable Sub Dispose(disposing As Boolean)
If disposed Then Return
If disposing Then
fs.Dispose()
' Free any other managed objects here.
'
End If
disposed = True
End Sub
End Class
메서드를 재정의 Object.Finalize 하는 경우 클래스는 다음 패턴을 구현해야 합니다.
using System;
class BaseClass2 : IDisposable
{
// Flag: Has Dispose already been called?
bool disposed = false;
// Public implementation of Dispose pattern callable by consumers.
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
// Protected implementation of Dispose pattern.
protected virtual void Dispose(bool disposing)
{
if (disposed)
return;
if (disposing)
{
// Free any other managed objects here.
//
}
// Free any unmanaged objects here.
//
disposed = true;
}
~BaseClass2()
{
Dispose(disposing: false);
}
}
open System
type BaseClass2() =
// Flag: Has Dispose already been called?
let mutable disposed = false
interface IDisposable with
// Public implementation of Dispose pattern callable by consumers.
member this.Dispose() =
this.Dispose true
GC.SuppressFinalize this
// Implementation of Dispose pattern.
abstract Dispose: bool -> unit
override _.Dispose(disposing) =
if not disposed then
if disposing then
// Free any other managed objects here.
()
// Free any unmanaged objects here.
disposed <- true
override this.Finalize() =
this.Dispose false
Class BaseClass : Implements IDisposable
' Flag: Has Dispose already been called?
Dim disposed As Boolean = False
' Public implementation of Dispose pattern callable by consumers.
Public Sub Dispose() _
Implements IDisposable.Dispose
Dispose(disposing:=True)
GC.SuppressFinalize(Me)
End Sub
' Protected implementation of Dispose pattern.
Protected Overridable Sub Dispose(disposing As Boolean)
If disposed Then Return
If disposing Then
' Free any other managed objects here.
'
End If
' Free any unmanaged objects here.
'
disposed = True
End Sub
Protected Overrides Sub Finalize()
Dispose(disposing:=False)
End Sub
End Class
서브클래스는 다음과 같이 삭제 가능한 패턴을 구현해야 합니다.
- 기본 클래스
Dispose(Boolean)
구현을 재정Dispose(Boolean)
의하고 호출해야 합니다. - 필요한 경우 종료자를 제공할 수 있습니다. 종료자는 을 호출
Dispose(false)
해야 합니다.
파생 클래스 자체는 인터페이스를 구현 IDisposable 하지 않으며 매개 변수가 없는 Dispose 메서드를 포함하지 않습니다. 기본 클래스 Dispose(Boolean)
메서드만 재정의합니다.
다음 코드 조각은 파생 클래스에 대한 삭제 패턴을 반영합니다. 형식이 메서드를 재정의하지 않는다고 가정합니다 Object.Finalize .
using System;
using System.IO;
using System.Runtime.InteropServices;
class MyDerivedClass : MyBaseClass
{
// Flag: Has Dispose already been called?
bool disposed = false;
// Instantiate a FileStream instance.
FileStream fs = new FileStream("test.txt", FileMode.OpenOrCreate);
// Protected implementation of Dispose pattern.
protected override void Dispose(bool disposing)
{
if (disposed)
return;
if (disposing)
{
fs.Dispose();
// Free any other managed objects here.
//
}
// Free any unmanaged objects here.
//
disposed = true;
// Call base class implementation.
base.Dispose(disposing);
}
}
open Microsoft.Win32.SafeHandles
open System
type MyDerivedClass() =
inherit MyBaseClass()
// Flag: Has Dispose already been called?
let mutable disposed = false
// Instantiate a FileStream instance.
let fs = new FileStream("test.txt", FileMode.OpenOrCreate)
// Implementation of Dispose pattern.
override _.Dispose(disposing) =
if not disposed then
if disposing then
fs.Dispose()
// Free any other managed objects here.
// Free any unmanaged objects here.
disposed <- true
// Call base class implementation.
base.Dispose disposing
Imports System.IO
Imports System.Runtime.InteropServices
Class DerivedClass2 : Inherits BaseClass2
' Flag: Has Dispose already been called?
Dim disposed As Boolean = False
' Instantiate a FileStream instance.
Dim fs As FileStream = New FileStream("test.txt", FileMode.OpenOrCreate)
' Protected implementation of Dispose pattern.
Protected Overrides Sub Dispose(disposing As Boolean)
If disposed Then Return
If disposing Then
fs.Dispose()
' Free any other managed objects here.
'
End If
' Free any unmanaged objects here.
'
disposed = True
' Call base class implementation.
MyBase.Dispose(disposing)
End Sub
End Class
.NET