Effective C# 3rd 読書メモ 21 ジェネリッククラスは必ずDisposableな型パラメータをサポートするようにする

ジェネリッククラスでIDisposableを実装している型を受け取る際は、適切にリソースを破棄する必要がある。
リソースの破棄には以下のようなイディオムが利用できる。

public void DoSomething()
{
    var something = new T();
    using (something as IDisposable)
    {
        something.DoSomething();
    }
}

somethingIDisposableを実装していない場合、キャストの結果は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();
    }
}

コメントを残す

コメントを残す