Disposeで簡単Destroy
コードが長くなってくるとやらかしやすい破棄漏れ(*1)。一時Texture2DとかMaterialとか、消しておかなきゃリークします。簡単なDispose()による対策をチラ裏。
abstract class OnDisposable : System.IDisposable { public bool isDisposed { get { return m_disposed; } } public void Dispose() { this.DoDispose(true); System.GC.SuppressFinalize(this); } protected virtual void OnDispose() { } private void DoDispose(bool flag) { if (m_disposed == false) OnDispose(); m_disposed = true; } ~OnDisposable() { this.DoDispose(false); } private bool m_disposed = false; } class ObjectDisposer : OnDisposable { public ObjectDisposer(UnityEngine.Object obj) : this(new UnityEngine.Object[] { obj }) { } public ObjectDisposer(params UnityEngine.Object[] objects) { m_objects = objects; } protected override void OnDispose() { if (m_objects != null) { foreach (UnityEngine.Object obj in m_objects) { if (obj != null) { if (Application.isEditor) DestroyImmediate(obj); else Destroy(obj); } } } } private UnityEngine.Object[] m_objects; }
使い方
Texture2D pxTex = new Texture2D(1, 1); Texture2D subTex = null; using (new ObjectDisposer(pxTex, subTex)) // まとめて登録 { if (条件とか) return; // returnやbreakしたって大丈夫。 subTex = new Texture2D(128, 128); System.String text = null; text.ToString(); // 例外 }
usingのスコープカッコを抜ける時Dispose()経由でキッチリDestroy。例外をゲロさせてもDispose()経由でpxTexやsubTexは削除してもらえるのがusing構文のウマウマなとこ。
*1:そんな気にしなくても大丈夫だろと思ってたらやっぱりやってた…ネストの途中でreturnできないんですよね。ウッカリスコープ抜けちゃって末尾のDelete処理を飛ばして抜けるのは典型的ミスですが、弊害はそれに限らず、長い処理でreturnとかbreak的なネスト脱出法を採用できずフローが無駄に複雑化してスパゲティまっしぐらとか、時にはgoto文なんて頭をよぎって「いやいやさすがにソレは」とか。