スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
Prev.    Category    Next 

C# インターフェース - IEnumerable(T)

今回は C# のインターフェースの IEnumerable<T> に関する説明です。
このインターフェースは非常に便利なのですが、 実装するにはちょっとしたテクニックが必要となります。 知らないとなかなか思いつきにくいところなので、 覚えておいて損はないと思います。

用途

前回紹介したIEnumerable インターフェース と同様に IEnumerable<T> は自作のコンテナークラス などで継承します。

IEnumerable を継承したクラスは foreach で使えるようになります。
IEnumerable<T> の場合は、 foreach で使えることに加えて、より大きなメリットがあります。

それは System.Linq using しておくことによって、 LINQ で定義された多くの拡張メソッドが使用可能になることです。 これは Ruby で言えば、 Enumerable を Mix-in したようなものです。
自前のコンテナークラスを用意した場合には、 IEnumerable<T> を継承しておくのがお勧めです。

実装するメソッド

IEnumerable<T> を継承するには GetEnumerator()メソッドを実装します。
IEnumerator<T> GetEnumerator();
加えて、 IEnumerator の GetEnumerator() メソッドも実装する必要があります。
IEnumerator GetEnumerator()
これは IEnumerator<T> が単に IEnumerator のジェネリック版というだけでなく、 IEnumerator を継承しているインターフェースだからです。
cs_ienumurator_t.png
IEnumerator<T> を継承すると IEnumerator も継承することになります。
実際にはIEnumerator<T> の GetEnumerator() しかまず使われません。 しかし、両方の GetEnumerator() メソッドを実装しないとコンパイルに失敗してしまいます。

この IEnumerator 側の GetEnumerator() の実装ではよく使われる常套句的な記述があります。

実装方法

サンプルを使ってこの IEnumerator<T> の実装方法を説明していきたいと思います。 コンパイル:
 > csc IEnumerableSample_T.cs
Jagged Array と呼ばれる 配列の配列 を自作のコンテナーのサンプルとします。
cs_jagged_array.png

IEnumerableSample_T.cs (クラス定義部) :
class JaggedArray<TSource> : IEnumerable<TSource>
{
    private List<TSource>[]  _list;
        
    public JaggedArray(int rowmax)
    {
        _list = new List<TSource>[rowmax];
    }
        
    public bool Add(int row, TSource val, params TSource[] restvals)
    {
        // :
    }
        
    public IEnumerator<TSource> GetEnumerator()
    {
        foreach (List<TSource> sublist in _list)
        {
            if (sublist != null)
            {
                // 子側の配列をイテレート
                foreach (TSource val in sublist)
                {
                    yield return val;
                }
            }   
        }
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }
}
この IEnumerable.GetEnumerator() の定義部分がポイントです。
IEnumerable のメソッドであることを IEnumerable. で明示的に指定しています。 これがないと戻り値だけが違うメソッドのオーバーロードとなり、コンパイルエラーとなります。
定義内は IEnumerable<T> の GetEnumerator() を呼び出すだけの処理です。


次に作成した JaggedArray を実際に使ってみます。
// 結果表示用のメソッド
static string Dump<TSource>(IEnumerable<TSource> source)
{
    return "{" + string.Join(", ", source) + "}";
}

static void Main()
{
    JaggedArray<int> jagary = new JaggedArray<int>(5);
    jagary.Add(0, 1);
    jagary.Add(2, 1, 2, 3, 4);
    jagary.Add(3, 1, 2);
    jagary.Add(4, 5);

    foreach (int it in jagary)
    {
        Console.Write("{0} ", it);
    }
    Console.WriteLine("\n");

    // LINQ
    Console.WriteLine("Count = {0}", jagary.Count());
    Console.WriteLine("3 Contains ? = {0}", jagary.Contains(3));
    Console.WriteLine("Max = {0}", jagary.Max());
    Console.WriteLine("Sum = {0}", jagary.Sum());
    Console.WriteLine("Average = {0}", jagary.Average());
    Console.WriteLine("ToArray = {0}", Dump(jagary.ToArray()));
    Console.WriteLine("(Source) / 2.0 = {0}", Dump(jagary.Select(it=>it/2.0)));
}
実行結果 :
1 1 2 3 4 1 2 5 

Count = 8
3 Contains ? = True
Max = 5
Sum = 19
Average = 2.375
ToArray = {1, 1, 2, 3, 4, 1, 2, 5}
(Source) / 2.0 = {0.5, 0.5, 1, 1.5, 2, 0.5, 1, 2.5}
まず foreach で要素を順にアクセスする処理を行なっています。

その後に LINQ の演算子メソッドの幾つかを使用しています。
これは多くの演算子メソッドの中のほんの一部です。 これらを自分で実装することなく、使用することができるようになっています。


関連記事
スポンサーサイト
Prev.    Category    Next 

Facebook コメント


コメント

コメントの投稿

Font & Icon
非公開コメント

このページをシェア
アクセスカウンター
アクセスランキング
[ジャンルランキング]
コンピュータ
28位
アクセスランキングを見る>>

[サブジャンルランキング]
プログラミング
4位
アクセスランキングを見る>>
カレンダー(アーカイブ)
プルダウン 降順 昇順 年別

07月 | 2017年08月 | 09月
- - 1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31 - -


はてな新着記事
はてな人気記事
ブロとも申請フォーム
プロフィール

yohshiy

Author:yohshiy
職業プログラマー。
仕事は主に C++ ですが、軽い言語マニアなので、色々使っています。

はてブ:yohshiy のブックマーク
Twitter:@yohshiy

サイト紹介
プログラミング好きのブログです。プログラミング関連の話題や公開ソフトの開発記などを雑多に書いてます。ただ、たまに英語やネット系の話になることも。
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。