ジェネリッククラスでIDisposable
を実装している型を受け取る際は、適切にリソースを破棄する必要がある。
リソースの破棄には以下のようなイディオムが利用できる。
public void DoSomething()
{
var something = new T();
using (something as IDisposable)
{
something.DoSomething();
}
}
something
がIDisposable
を実装していない場合、キャストの結果はnull
になるので、usingのブロックは実行されない。
ジェネリッククラス自身がIDisposable
を実装しなければならない場合、実装はやや面倒になる。
public sealed class Something<T> : IDisposable
where T : ISomething, new()
{
private Lazy<T> _something = new Lazy<T>(() => new T());
public void DoSomething() => _something.Value.DoSomething();
public void Dispose()
{
if (_something.IsValueCreated)
{
var r = _something.Value as IDisposable;
r?.Dispose();
}
}
}
ここでは、クラスをsealed
にすることで、Dispose
が必ず実行されるようにしている。
リソースの生成・破棄をクラスの責務から外すことで、実装を簡素化することもできる。
public sealed class Something<T> where T : ISomething
{
private readonly T _something;
public Something(T something)
{
_something = something;
}
public void DoSomething()
{
_something.DoSomething();
}
}