Open6
IDisposable活用法
Factoryパターン + IDisposableは便利
操作の終了をDispose()
だけで出来ちまうんだ
public static IDisposable BindTo (this IPool pool,IReadOnlyTimer timer,int keep) {
return new TimerBinding(pool,timer,keep);
}
class TimerBinding : IDisposable {
readonly IReadOnlyTimer m_Timer;
readonly IPool m_Pool;
readonly int m_Keep;
bool m_IsDisposed;
public TimerBinding (IPool pool,IReadOnlyTimer timer,int keep) {
m_Pool = pool;
m_Timer = timer;
m_Keep = keep;
m_Timer.OnElapsed += OnElapsed;
}
public void Dispose () {
if (m_IsDisposed) {
return;
}
m_IsDisposed = true;
m_Timer.OnElapsed -= OnElapsed;
}
void OnElapsed () {
m_Pool.ReleaseInstances(m_Keep > m_Pool.Capacity ? m_Pool.Capacity : m_Keep);
}
}
UniRxにもあるけど、IDisposable
を結合する関数があると便利
public static IDisposable Combine (IDisposable disposable1,IDisposable disposable2) {
return new Binary(disposable1,disposable2);
}
class Binary : IDisposable {
readonly IDisposable m_Disposable1;
readonly IDisposable m_Disposable2;
public Binary (IDisposable disposable1,IDisposable disposable2) {
m_Disposable1 = disposable1;
m_Disposable2 = disposable2;
}
public void Dispose () {
m_Disposable1.Dispose();
m_Disposable2.Dispose();
}
}
タプルで結合出来たら最高じゃね!?と思ったけど許されていなかった
public static IDisposable Combine (this (IDisposable disposable1,IDisposable disposable2) source) {
return new Binary(source.disposable1,source.disposable2);
}
オブジェクトプールでの借用トークンとしてIDisposable
を返して、outでインスタンスを手法。
public static RentInstance<T> RentTemporary<T> (this IPool<T> pool,out T instance) {
if (pool == null) {
throw Error.ArgumentNullException(nameof(pool));
}
instance = pool.Rent();
return new RentInstance<T>(pool,instance);
}
public struct RentInstance<T> : IDisposable {
readonly T m_Instance;
readonly IPool<T> m_Pool;
internal RentInstance (IPool<T> pool,T instance) {
m_Pool = pool;
m_Instance = instance;
}
public void Dispose () => m_Pool.Return(m_Instance);
}
usingステートメントとの合わせ技で簡単に使えて最高
using (pool.RentTemporary(out T instance)) {
// このブロック内だけ、プールからインスタンスを借りる
}
最近よくやるやつ
// スクリーンをブロック(内部的に参照カウントを増やす)
using (m_ScreenBlocker.Block()) {
// 何かしらの待機処理
}
Navigathenaの処理カウントでやったやつ
using var _ = m_ProcessCounter.Increment();
関数のスコープ内で使うことで、スコープを抜けたら勝手に解放される。これによって、usingブロックによるネストを発生させなくても良くなる。ただし、変数の定義の部分は完全に無駄感ある