yield return
イテレータを簡単に書けるyield returnが便利で好きなのだけれど、以下のようなのが書けたらなーと思ったのでメモ。
using System; using System.Collections.Generic; class Hoge : IEnumerable<int> { int[] _a; int _b; int[] _c; public Hoge(int[] a, int b, int[] c) { _a = a; _b = b; _c = c; } public IEnumerator<int> GetEnumerator() { if (_a != null) return _a.GetEnumerator(); // returnでもyield returnでもエラー yield return _b; if (_c != null) return _c.GetEnumerator(); // 同上 } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); } } class App { public static void Main(string[] args) { int[] a = new int[]{1, 2}; int b = 3; int[] c = new int[]{4, 5, 6}; Hoge h = new Hoge(a, b, c); // 1 2 3 4 5 6 って走査できたらなぁ... foreach(int n in h) { Console.Write(n + " "); } } }
これができると、木構造のトラバースが簡単になるなー、みたいな。こんな感じ。
// 2分木のノード class Node : IEnumerable<int> { int _val; Node _left; Node _right; // ... 略 ... public IEnumerator<int> GetEnumerator() { if (_left != null) return _left.GetEnumerator(); yield return _value; if (_right != null) return _right.GetEnumerator(); } } // 2分木 class Tree : IEnumerable<int> { Node _root; // ... 略 ... public IEnumerator<int> GetEnumerator() { if (_root == null) yield break; else { yield return _root.GetEnumerator(); } } }
要素をなめるだけなら
class Node { // ... 略 ... void ForEach(Action<int> action) { if (_left != null) _left.ForEach(action); action(_val); if (_right != null) _right.ForEach(action); } }
とかやれば良いけど、IEnumerableにしたい。TreeNodeEnumeratorクラスを作るのを面倒くさく思ったのがキッカケだけど、気付いてないだけで簡単な方法がありそうだな...。うーん...。