🌍 C# Study/이펙티브 C#
[21] 타입 매개변수가 IDisposable을 구현한 경우를 대비하여 제네릭 클래스를 작성하라
맨텀
2021. 4. 27. 14:11
다음 본문은 도서 이펙티브 C# (빌 와그너)에서 나오는 주제를 다룹니다.
제약조건은 타입 매개변수가 할 수 있는 것을 규정하지만, 무엇을 해서는 안 되는지는 규정하지 않는다.
제약조건이 요구하는 작업 외에는 신경을 쓰지 않는다는 것이다.
하지만 IDisposable을 구현하고 있다면 추가 작업이 필요하다.
메소드 내에서 타입 객체를 생성한 경우
- T가 IDisposable을 구현한 타입일경우 그냥 생성하고 사용하기만하면 리소스 누수가 발생할 수 있다.
- T가 IDisposable을 구현했다면 using 블록이 끝날 때 Dispose()를 호출한다.
public void GetThingsDone()
{
T driver = new T();
using(driver as IDisposable)
{
diriver.DoWork();
}
}
클래스 내의 멤버로 타입 객체를 선언한경우
- T가 IDisposable을 구현했을 가능성이 있다면 클래스 내에서 IDisposable을 구현하여 해당 리소스를 처리해야한다.
public sealed class EngineDriver2<T> : IDisposable where T : IEngine, new()
{
private Lazy<T> driver = new Lazy<T>(() => new T());
public void GetThingsDone() => driver.Value.Dowork();
public void Dispose()
{
if(driver.IsValueCreated)
{
var resource = driver.Value as IDisposable;
resource?.Dispose();
}
}
}
- 제네릭 클래스의 코드가 복잡해 지는 것을 원하지 않는다면, 객체의 소유권과 Dispose의 호출책임을 외부로 넘겨 new() 제약조건을 제거할 수 있다.
public sealsed class EngineDriver<T> where T : IEngine
{
private T driver;
public EngineDriver(T driver)
{
this.driver = driver;
}
public void GetThingsDone()
{
driver.DoWork();
}
}
결론
- 타입 매개변수를 사용하는 경우 리소스가 누수되지않도록 주의하자.