ITEM 21 :: EFFECTIVE C#
안녕하세요, 21번째 시간입니다. 반가운 우리의 IDisposable.
이번 챕터는 타입 매개변수가 Idisposable을 구현한 경우를 대비하여 제네릭 클래스를 작성하라, 입니다. 이 부분에 대해서는 어느정도 이해가 되었지만, 그래도 이 정도까지 제네릭을 쓸 상황이 올지 모르겠습니다. 개인 프로젝트로 시작을 해봐야 하나 고민하는 지금, 만약 제네릭을 사용하는 C# 유저라면 이팁이 매우, 중요한 팁이 아닌가 싶습니다.
설명
제약조건은 두 가지 역할을 한다. 하나는 런타임 오류가 발생할 가능성이 있는 부분을 컴파일 타임 오류로 대체하여 조금 더 빠르게 오류를 찾아낼 수 있다. (제약조건을 사용하면 런타임에 타입확인을 하지 않고, 컴파일 타임에 타입확인을 한다.) 두번째로는 타입 매개변수로 사용할 수 있는 타입을 명확히 규정하여 사용자에게도 도움을 준다.
하지막 제약조건은 타입 매개변수가 무엇을 해야 하는지만을 규정할 수 있고, 무엇을 해서는 안 되는지를 정의할 수 없다. 말 그대로 타입에 대한 제약조건이니까.
따라서, 대부분의 경우 타입 매개변수로 지정하는 타입이 제약조건을 통해요구하는 작업 외에 다른 작업을 추가로 수행할 수 있는지에 대해서 신경 쓰지 않는다. 하지만 타입 매개변수로 지정하는 타입이 IDisposable을 구현하고 있다면 특별한 추가작업을 해주어야 한다.
여담으로 실제 사례는 조금 복잡하다. 즉, 실제로 발생하기는 어려운 문제라는 점, 알고 있길 바란다. 하지만, 발생하면 리소스 누수가 되므로 치명적인 문제를 야기할 수 있으므로 주의 해야 한다.
발생조건은 타입매개변수가 IDisposable을 구현할 타입일경우 발생할 수 있다. 따라서, 타입 매개변수가 실제로 IDisposable을 구현했는지 확인해야하며, 구현했다면 추가적인 처리를 해주어야 한다.
Public void GetThingsDone()
{
T driver = new T();
using (driver as Idisposable)
{
driver.Dowork();
}
}
이처럼 코드를 작성하면 컴파일러는 IDisposable로 형변환 된 객체를 저장하기 위해서 숨겨진 지역변수를 생성한다. 이 때, 만약 T가 IDisposable을 구현하지 않았다면, 이 지역변수 값은 null이 된다. C#컴파일러는 이 지역변수의 값이 null인지 검사한 후 Dispose()를 호출하도록 코드를 생성하기 때문에, 지역 변수의 값이 null인 경우, Dispose()가 호출되지 않는다. 반대로, 구현했다면 using 블록을 빠져나갈 때 Dispose()를 호출한다.
고래서 결론은?
제네릭 클래스의 타입 매개변수로 객체를 생성하는 경우 이 타입이 IDisposable을 구현하고 있는지를 확인해야 한다는 것이다. 항상 방어적으로 코드를 작성하고 객체가 삭제될 때 리소스가 누수되지 않도록 주의해야한다.