개발공부/C#

[Effective C#] 아이템 21 : 타입 매개변수가 IDisposable을 구현한 경우를 대비하여 제네릭 클래스를 작성하라

개발자 찐빵이 2021. 11. 27. 20:14
728x90

제약 조건의 역할

  1. 런타임 오류가 발생할 가능성이 있는 부분을 컴파일 타임 오류로 대체한다.
  2. 타입 매개변수로 사용할 수 있는 타입을 명확히 규정하여 사용자에게 도움을 준다.

제약조건은 타입 매개변수가 무엇을 해서는 안되는지를 정의할 수 없다.
이때, 타입 매개변수로 지정하는 타입이 IDisposable을 구현하고 있다면 추가 작업이 필요하다.

제네릭 메서드 내에서 타입 매개변수로 주어지는 타입을 이용하여 인스턴스를 생성할 경우

public interface IEngine
{
    void DoWork();
}

public class EngineDriverOne<T> where T : IEngine, new()
{
    public void GetThingsDone()
    {
        T driver = new T();
        using (driver as IDisposable)
        driver.Dowork();
    }
}

설명

IDisposable로 형변환된 객체를 저장하기 위해 숨겨진 지역변수를 생성한다.
만약 T가 IDisposable을 구현하지 않았다면 이 지역변수의 값은 null이 된다.
타입 매개변수로 주어진 타입을 이용하여 인스턴스를 생성하는 경우, 반드시 using 문을 사용해야 한다.
또한 해당 타입이 IDisposable을 구현했는지 알 수 없으므로 형변환을 해줘야 한다.

C# 컴파일러가 하는 일

  1. 지역변수 값이 null인지 검사
  2. Dispose()를 호출하도록 코드 생성

따라서 지역변수의 값이 null인 경우 Dispose()가 호출되지 않는다.
반대로 T가 IDisposable을 구현했다면 using 블록을 종료할 때 Dispose()가 호출된다.

결론

  • 제네릭 클래스의 타입 매개변수로 객체를 생성하는 경우, 이 타입이 IDisposable을 구현하고 있는지 확인해야 한다.
  • 항상 방어적으로 코드를 작성하고 객체가 삭제될 때 리소스가 누수되지 않도록 주의해야 한다.
  • 코드를 수정하여 타입 매개변수 객체를 생성하지 않도록 할 수 있지만, 타입 매개변수로는 지역변수 정도만 생성하는 것이 좋다.
  • 타입 매개변수로 멤버 변수를 선언해야 하는 경우 지연 생성을 사용하거나 제네릭 클래스에서 IDisposable을 구현해야 할 수 있다.
반응형