IDisposable
な構造体について。
アロケーションを避けるために構造体を使用したとしても、IDisposable
インターフェースが噛む using ではbox化が発生するのでは――?
との疑問も浮かぶが、具象で using するケースでは発生しない。(devirtualization? 違うかも)
参考:
structをusing-statementで使用したらboxingが発生するのか - えんじにあ雑記!
構造体なら処理ひとつを包むのに使うハードルが低い。
というわけで包むぞ!
後処理を考えると少し不格好になってしまうような、例としてArrayPool
を考える。
// const int SIZE; byte[]? buf = null; try { buf = ArrayPool<byte>.Shared.Rent(SIZE); // 処理 } finally { if (buf is not null) ArrayPool<byte>.Shared.Return(buf); }
リソース後処理の try~finally は普通だけれど、using IDisposable
の見た目になれると少しぎこちなく見えてしまう。
そこで、ラッパーを考えてみる。
internal readonly struct ArrayPoolWrapper<T> : IDisposable { public readonly int Length; private readonly T[] array; public ArrayPoolWrapper(int length) { Length = length; array = ArrayPool<T>.Shared.Rent(length); } public Memory<T> AsMemory() => array.AsMemory(0, Length); public Span<T> AsSpan() => array.AsSpan(0, Length); public void Dispose() => ArrayPool<T>.Shared.Return(array); }
using ArrayPoolWrapper<byte> buf = new(SIZE); // Span や Memory を通して処理
個人的にはやはり、try~finally より using の方が馴染む。