2007年05月29日

独自クラスでforeach を書けるようにするには

   このエントリーをはてなブックマークに追加 Clip to Evernote
自分の知識を整理する意味で、まとめてみました。

foreachが使える最も簡単な独自のクラスを作成するには、以下のように書けばよい。

public class MyCollection  {
public IEnumerator GetEnumerator() {
yield return 1;
yield return 2;
yield return 3;
yield return 4;
}
}

こうすれば、

MyCollection col = new MyCollection();
foreach ( int n in col ) {
Console.WriteLine(n);
}

のように、foreachが書ける。GetEnumerator() というメソッドがあれば、IEnumerable を継承する必要はない。

しかし、MoveNext,Currentを使うことはできない。

MyCollection col = new MyCollection();
IEnumerator ite = col.GetEnumerator();
while ( ite.MoveNext() ) {
int n = ite.Current;
Console.WriteLine(n);
}

と書いても、MoveNextが無いとエラーになってしまう。
これに対応するには、IEnumerableインターフェースから継承する必要がある。

public class MyCollection : IEnumerable {
public IEnumerator GetEnumerator() {
yield return 1;
yield return 2;
yield return 3;
yield return 4;
}
}

しかし、

    int n = ite.Current; 

でキャストできないとエラーになるので、

    int n = (int)ite.Current; 

としてあげなければならない。このキャストを不要にするには、ジェネリックなIEnumerableを継承すればよい。

public class MyCollection : IEnumerable<int> {
public IEnumerator<int> GetEnumerator() {
yield return 1;
yield return 2;
yield return 3;
yield return 4;
}

IEnumerator IEnumerable.GetEnumerator() {
return GetEnumerator();
}
}

こうすれば、

MyCollection col = new MyCollection();
IEnumerator<int> ite = col.GetEnumerator();
while ( ite.MoveNext() ) {
int n = ite.Current;
Console.WriteLine(n);
}

と書ける。
IEnumerableから継承したものと比べると、書く手間はかえって増えているが、より安全なコードにはなっている。

ただ、foreachしか使わないのならば、最初のコードで十分だろう。

ところで、単に独自の型指定のコレクションを作るだけならば、System.Collections.ObjectModel.Collectionを継承するだけでもよい。

class MyList : System.Collections.ObjectModel.Collection<int> {
}

これだけで、GetEnumerator はもちろん、Add, Insert, Remove, IndexOf, Clear などのメソッドが利用可能だ。


この記事へのコメント
yield って最初いまいちわかりにくかったんですが、
このように順に説明されているととても解りやすいですね。
Posted by かるあ at 2007年05月29日 21:25
MVPのかるあさんにそう言っていただき光栄です。(^_^)
yieldって、確かにはじめは不思議に思うけど、慣れてしまうとものすごく簡単で、昔のやり方に戻ることは出来ませんね。

Posted by Gushwell at 2007年05月30日 09:07
 

この記事へのトラックバックURL

http://trackback.blogsys.jp/livedoor/gushwell/50808678
この記事へのトラックバック
久しぶりにプログラムなんぞをやってますんで、独自の型をコレクションするクラスに各種有名どころなメソッドを実装するのさえ面倒くさくなっております。 というかいまいちそこら辺のインターフェイスって消化できてなかったり。 んなもんで .NET Framework 2.0 になって....
なんてことだ、こんな簡単にコレクションが!!【TEMTECOMAI ORTHOSTATIC HYPOTENSION】at 2007年06月18日 21:47