IDisposable과 using 문
Coddy C# 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨 — 70개 중 45번째.
일부 객체는 가비지 컬렉터가 자동으로 정리할 수 없는 리소스(파일 핸들, 데이터베이스 연결, 네트워크 소켓 등)를 보유합니다. IDisposable 인터페이스는 이러한 리소스의 사용이 끝났을 때 이를 해제하는 표준 방법을 제공합니다.
클래스는 Dispose() 메서드를 제공하여 IDisposable을 구현합니다:
public class FileHandler : IDisposable
{
private bool disposed = false;
public void Dispose()
{
if (!disposed)
{
Console.WriteLine("Releasing resources...");
disposed = true;
}
}
}Dispose()를 수동으로 호출할 수도 있지만, 해당 라인에 도달하기 전에 예외가 발생하면 어떻게 될까요? using 문은 문제가 발생하더라도 정리가 수행됨을 보장합니다:
using (FileHandler handler = new FileHandler())
{
// 핸들러를 사용하여 작업합니다
} // 여기서 Dispose()가 자동으로 호출됩니다최신 C#은 using 선언을 통해 더 깔끔한 구문을 제공하며, 이는 객체가 범위를 벗어날 때 객체를 해제(dispose)합니다:
void ProcessFile()
{
using FileHandler handler = new FileHandler();
// handler 작업
} // 메서드 종료 시 Dispose()가 호출됨using 문은 IDisposable을 구현하는 모든 형식과 함께 작동합니다. StreamReader, SqlConnection, HttpClient와 같은 기본 제공 클래스들은 모두 이 인터페이스를 구현하므로, 적절한 리소스 관리를 간단하고 안정적으로 수행할 수 있습니다.
챌린지
쉬움IDisposable 인터페이스와 using 문을 사용하여 적절한 리소스 관리를 보여주는 데이터베이스 연결 시뮬레이터를 만들어 보겠습니다. 연결이 열리고 닫히는 시점을 추적하여 리소스가 항상 올바르게 해제되도록 보장하는 클래스를 작성하게 됩니다.
코드는 두 개의 파일로 구성됩니다:
DatabaseConnection.cs:DataAccess네임스페이스 안에IDisposable을 구현하는DatabaseConnection클래스를 생성합니다. 이 연결 클래스는 다음을 수행해야 합니다:- 생성자를 통해 설정되는
ConnectionName속성(문자열, 읽기 전용)을 가집니다. - 프라이빗 불리언 필드를 사용하여 연결이 해제(disposed)되었는지 여부를 추적합니다.
- 객체가 생성될 때(생성자에서)
Connection opened: {ConnectionName}를 출력합니다. Dispose()메서드를 구현하여Connection closed: {ConnectionName}를 출력합니다. 단, 이미 해제된 경우에는 출력하지 않아야 합니다(중복 해제 방지).Executing on {ConnectionName}: {sql}를 반환하는Query(string sql)메서드를 가집니다.
- 생성자를 통해 설정되는
Program.cs: 메인 파일에서 데이터베이스 연결과 함께using문을 사용하여 적절한 리소스 관리를 보여줍니다. 연결을 생성하고, 쿼리를 실행하며,using블록이 자동으로 정리를 처리하도록 합니다.
두 개의 입력을 받게 됩니다:
- 연결 이름 (예:
MainDB) - 실행할 SQL 쿼리 (예:
SELECT * FROM Users)
using 문을 사용하여 연결을 생성하세요. 블록 내부에서 Query 메서드를 호출하고 그 결과를 출력합니다. using 블록이 끝나면 Dispose()가 자동으로 호출됩니다.
예를 들어, 입력이 MainDB와 SELECT * FROM Users라면 출력은 다음과 같아야 합니다:
Connection opened: MainDB
Executing on MainDB: SELECT * FROM Users
Connection closed: MainDBusing 블록이 끝날 때 연결이 어떻게 자동으로 닫히는지 확인해 보세요. Dispose()를 수동으로 호출할 필요가 없습니다. 이 패턴은 블록 내부에서 예외가 발생하더라도 리소스가 항상 정리되도록 보장합니다!
치트 시트
IDisposable 인터페이스는 가비지 컬렉터가 자동으로 정리할 수 없는 리소스(파일 핸들, 데이터베이스 연결, 네트워크 소켓 등)를 해제하는 표준 방법을 제공합니다.
클래스는 Dispose() 메서드를 제공함으로써 IDisposable을 구현합니다:
public class FileHandler : IDisposable
{
private bool disposed = false;
public void Dispose()
{
if (!disposed)
{
Console.WriteLine("Releasing resources...");
disposed = true;
}
}
}using 문은 예외가 발생하더라도 정리가 자동으로 수행되도록 보장합니다:
using (FileHandler handler = new FileHandler())
{
// handler를 사용하여 작업 수행
} // 여기서 Dispose()가 자동으로 호출됨최신 C#은 using 선언을 통해 더 깔끔한 구문을 제공합니다:
void ProcessFile()
{
using FileHandler handler = new FileHandler();
// handler를 사용하여 작업 수행
} // 메서드가 종료될 때 Dispose()가 호출됨using 문은 StreamReader, SqlConnection, HttpClient와 같은 내장 클래스를 포함하여 IDisposable을 구현하는 모든 형식에서 작동합니다.
직접 해보기
using System;
using DataAccess;
class Program
{
public static void Main(string[] args)
{
string connectionName = Console.ReadLine();
string sqlQuery = Console.ReadLine();
// TODO: 'using' 문을 사용하여 DatabaseConnection을 생성하세요.
// using 블록 내부에서:
// 1. sqlQuery를 사용하여 Query 메서드를 호출하세요.
// 2. Query 메서드의 결과를 출력하세요.
// using 블록이 끝나면 Dispose 메서드가 자동으로 호출됩니다.
}
}
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
객체 지향 프로그래밍의 모든 레슨
8심화 OOP 개념
상속보다 합성(Composition)제네릭 (클래스 및 메서드)델리게이트와 이벤트어트리뷰트와 리플렉션IDisposable과 using 문Dependency Injection 기초