C#に元々ある機能で学ぶデザインパターン "Iterator Pattern"
概要
何番煎じか分かりませんが、イテレータパターン(Iterator Pattern)のお話です。
C#においては、言語に組み込まれていると言って良いでしょう。
Iterator パターン @ Wikipediaのクラス図に合わせた形で、C#の機能を説明していきます。
型
Aggregate -----------------> Iterator
△ △
│ │
Concrete Concrete
Aggregate -----------------> Iterator
IEnumerator<T>
Aggregate -----------------> Iterator
△ △
│ │
Concrete Concrete
Aggregate -----------------> Iterator
IEnumerator<T>
デザインパターンで出てくるIterator
インタフェースは、C#ではIEnumerator<T>
に当たります。
『列挙する者』みたいな意味(Enumurate + -or)ですね。
Current
,MoveNext()
next()
,hasNext()
は、C#ではCurrent
,MoveNext()
のように少し違った形で実装されます。
interface IEnumerator<out T> {
// 現在の要素を取得する。
T Current { get; }
// 次の要素に移動する。次の要素があればtrue,無ければfalseを返す。
bool MoveNext();
// その他の定義は省略
}
IEnumerable<T>
デザインパターンで出てくるAggregate
インタフェースは、C#ではIEnumerable<T>
に当たります。
『列挙可能』みたいな意味(Enumurate + -able)ですね。
GetEnumerator()
iterator()
メソッドは、C#ではGetEnumerator()
に当たります。
interface IEnumerable<out T> {
// イテレータを取得
IEnumerator<T> GetEnumerator();
// その他の定義は省略
}
IEnumerable<T>
を実装した型
ConcreteAggregate
に当たるC#の型は無数にあります。
同一の型のインスタンスを複数扱うようなデータ型はほぼこれに当てはまると思って良いでしょう。
- 配列
List<T>
Dictionary<TKey,TValue>
IEnumerator<T>
を実装した型
IEnumerator<T>
を実装した型は、例えばList<int>.Enumerator
型などがあります。
ただ、こちらは実装型を意識せずに利用することが普通ですね。
組み込まれている機能
foreach構文
foreach構文では、GetEnumerator()
メソッドを持つインスタンスであれば、同一の構文で要素を列挙できます。
これはC#プログラマなら無意識レベルで使っているであろう例です。
foreach (var item in obj) {
Console.WriteLine(item);
}
↑の構文は↓とほぼ同義になります。
var iterator = obj.GetEnumerator();
while (iterator.MoveNext()) {
Console.WriteLine(iterator.Current);
}
// 実際には例外処理や後処理などがあるが、ここでは省略
LINQ
LINQ to Objectでは、IEnumerable<T>
を『流れるようなインタフェース』として扱うことで、様々な標準クエリを利用可能にしています。
Enumerable
.Range(3, 10)
.Where(i => i % 2 == 1)
.Select(i => new { A = i, B = i * i / 2, C = i * i / 2 + 1 })
.ToList()
.ForEach(Console.WriteLine);
ジェネレータ
C#ではIEnumerable<T>
を利用したイテレータを生成するための構文が用意されています。
自前でIEnumerable<T>
とIEnumerator<T>
を作成する手間は基本的に不要と言えます。
(少しややこしいのですが、この構文は"Iterator block"と呼ばれます。)
// イテレータ構文と呼ばれているが、実際にはジェネレータ
static IEnumerable<int> Generate5Primes() {
yield return 2;
yield return 3;
yield return 5;
yield return 7;
yield return 11;
}
// 無限ループも使い方次第
static IEnumerable<double> RandomDoubles() {
var random = new Random();
while (true) {
yield return random.NextDouble();
}
}
まとめ
"Gang of Four"によるデザインパターンの紹介が1994年のことになります。つまり、C#に限らずその後にリリースされた言語ではこれらのデザインパターンが言語に取り込まれていることも多いのです。
これからデザインパターンを勉強しようとしている人は、自分の得意とする言語(やフレームワーク)にどのようなデザインパターンが組み込まれているのかを調べてみると良いと思います。
Author And Source
この問題について(C#に元々ある機能で学ぶデザインパターン "Iterator Pattern"), 我々は、より多くの情報をここで見つけました https://qiita.com/muniel/items/30809cae57d5a53a0e91著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .