C# ジェネリック コレクションを操作する(IEnumerableインターフェース)

   

今回は、IEnumerable<T>インターフェースの基本について書きます。
IEnumerable<T>を説明するときにはIEnumerator<T>がついてきます。

この2つのインターフェースは関係があり、IEnumerable<T>のGetEnumerator()は戻り値がIEnumerator<T>型なのです。

 

IEnumerable<T>の説明

MSDNでの解説は、
「指定した型のコレクションに対する単純な反復処理をサポートする列挙子を公開します。」
となっています。

 

反復処理と列挙子

「反復処理」は、while 、 do 、 for 、 foreach などのキーワードによる処理のことです。

「サポートする列挙子」ですが、意外に「列挙子」についての説明は少ないものです。
「列挙子」で検索すると、enum(列挙型)のほうがよくヒットします。

本題に戻って、列挙子ですが、列挙は

「並べあげること。一つ一つ数えあげること」

です。「列挙子=列挙するもの」とすると

「並べあげるモノ。一つ一つ数えあげるモノ」

となります。

「コレクションに対して数えるモノを公開してるだけ?」と思われると思います。

はい、IEnumerable<T>、IEnumerator<T>インターフェースの役割はそれだけです。

IEnumerable<T>インターフェースにプロパティはありません。
IEnumerator<T>インターフェースには、Currentプロパティがあります。

 

object Current コレクション内の現在の要素を取得します

 

IEnumerable<T>、IEnumerator<T>インターフェースのメソッド

IEnumerable<T>インターフェースのメソッドですが、IEnumerator<T> GetEnumerator()1つしかありません。

IEnumerator GetEnumerator() コレクションを反復処理する列挙子を返します。

 

IEnumerator<T>インターフェースのメソッドは2つあります。

bool MoveNext() 列挙子をコレクションの次の要素に進めます。
戻り値がbool型で、正常に次の要素にうつった場合はtrue、最後の要素の次にいった場合はfalseを返します。
void Reset() 列挙子を初期位置、つまりコレクションの最初の要素の前に設定します。

 

コレクションでIEnumeratorを継承する理由

コレクションというのは「ある型の項目の集まり」です。項目も少ないものから多いものまでいろいろあります。
プログラムでは、この「項目の集まり」に必ず”何か”します。

  • 「項目の集まり」からある条件に合致するものを探し出す。
  • 「項目の集まり」すべてを操作する。

など・・・こういった操作を行うときには、さきほど出てきた「反復処理」を使用します。

なのでこの「反復処理」を行うためのものとして「IEnumerable、IEnumerable<T>インターフェース」が存在しています。
(ちなみにC++では、反復子[イテレータ]があります)

逆にC#のコレクションなのに、このforeach文が使えないのはとても不便に感じます。

ジェネリックコレクションに限らず、自分で作ったコレクションクラスを公開する可能性がある場合は、このIEnumerable、IEnumerable<T>インターフェースを継承したほうがよいでしょう。
それは、「ジェネリックコレクションと同じようにforeach文などが書けるようになる」からです。

 

IEnumerator<T>、IEnumerable<T>インターフェースの実装

説明だけだと、とてもシンプルなイメージですが、実装はややこしい(ロジックなどではなく、ここまででもお分かりいただけたかと思いますが、この2つのインターフェースはスペルが非常によく似ています)

今回のサンプルでは、実際のプログラムなどではなくてもいいですが、List<string>を「項目の集まり」と見立てて、foreach文でアクセスするサンプルです。

 

今回は、StringListクラスは、IEnumerable<string>の説明のため、IEnumerable<string>のみの派生クラスとして作成しましたが、StringListクラスがICollection<string>も継承しているとコレクションクラスになります。

 

 

 - 未分類