読者です 読者をやめる 読者になる 読者になる

がりらぼ

WindowsRuntimeの応援ブログ

C#の主要インターフェース解説:IEnumerable<T>

IEnumerable<T>

前回、IEnumerableについて解説しました。 今回はIEnumerable<T>についてです。

IEnumerableは、ただのIEnumerableのジェネリック版ではなく、「LINQで処理することができる」というところが違います。

もちろんforeachで処理も可能です。なぜなら、「IEnumerable<T>はIEnumerableインターフェースを継承しているから」です。

IEnumerableはforeachで処理できるようになるインターフェースだと前回解説しました。

つまりIEnumebrale<T>はforeachとLINQで処理できるようになるクラスをつくることができるインターフェースです。

LINQ

LINQとは、コレクションをクエリで操作することができるC#の機能の一つです。

List<int> collection=new List<int>();
collection.Add(0);
collection.Add(1);
collection.Add(2);

というようなListがあると、

collection.Where(q=>q==1).Select(q=>q).ToList();

のように、通常ならばfor文なので複数行で処理しなければいけないコレクションを1行で処理できるヤツです。

LINQはSystem.Linq名前空間をつけるだけで拡張メソッドとして使うことができますが、IEnumerable<T>を実装しているクラスしかつかうことができません。

C#のListコレクションはIEnumerable<T>インターフェースを実装しているのでLINQでもforeachでも処理をおこなうことができます。

IEnumerable<T>を実装してみる

IEnumebrable<T>が実装を保証するメソッドIEnumerable<T>を返すGetEnumeratorメソッドとIEnumerableインターフェースのGetEnumeratorメソッドの2つです。

なぜなら、IEnumerable<T>インターフェースはIEnumerableインターフェースを実装しますが、インターフェースで実装を行うことはできないのでIEnumerable<T>インターフェースを実装するクラスでIEnumerableのGetEnumeratorメソッドも実装する必要があるからです。

では実際に実装したクラスを見てみましょう。

public class MyCollection<T>:IEnumerable<T>
{
    List<T> hoge;
    public MyCollection()
    {
        hoge=new List<T>();
    }

    public void AddObject(T item)
    {
        hoge.Add(item);
    }


    public IEnumerator<T> GetEnumerator()
    {
        for (int i = 0; i < hoge.Count; i++)
        {
            if (i % 2 == 0)
                yield return hoge[i];
        }
    }

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

IEnumerable<T>を返すGetEnumeratorは前回と同じようにforeachで処理したいコレクション要素を順にyield returnを行うだけです。今回は偶数番の要素をyield returnしています。

IEnumerableの方のGetEnumeratorメソッドは単純にIEnumerable<T>を返すGetEnumeratorを返せばいいだけです。

たったこれだけの実装で自作コレクションをLINQに対応させることができます。

実行してみる

では実際にIEnumerable<T>を実装したクラスを使ってみます。

MyCollection<int> collection = new MyCollection<int>();
collection.AddObject(0);
collection.AddObject(1);
collection.AddObject(2);
collection.AddObject(3);
collection.AddObject(4);
collection.AddObject(5);

foreach (int i in collection)
{
    Console.WriteLine(i);
}

List<int> orderd=collection.OrderByDescending(q => q).ToList();
foreach (int i in orderd)
{
    Console.WriteLine(i);
}

もちろんforeachでも処理できますし、LINQの拡張メソッドの一つであるOrderByDescendingメソッドやToListメソッドで並び替えやList化も可能となりました。

まとめ

  • IEnumerable<T>はコレクションをLINQとforeachで処理できるようにするインターフェース
  • IEnumerable<T>を実装するにはIEnumerator<T>を返すGetEnumeratorとIEnumeratorを返すGetEnumeratorを実装する必要がある
  • 実装方法は前回とおなじでイテレータ(yield return)を使う