ホーム C#のイテレータ

ベースとするコード

static void Main(string[] args)
{
    DateTime d = DateTime.Now;
    foreach (var i in f(1, 10))
    {
        Console.WriteLine((DateTime.Now - d).Seconds.ToString());
        if (i == 3) { break; }
    }
    Console.ReadLine();
}

static List<int> f(int s, int e)
{
    List<int> result = new List<int>();
    for (int i = s; i <= e; i++)
    {
        // 重い処理があるとする
        Thread.Sleep(1000);
        result.Add(i);
    }
    return result;
}

実行結果

10
10
10

外部イテレータ

static void Main(string[] args)
{
    DateTime d = DateTime.Now;
    foreach (var i in f(1, 10))
    {
        Console.WriteLine((DateTime.Now - d).Seconds.ToString());
        if (i == 3) { break; }
    }
    Console.ReadLine();
}

static IEnumerable<int> f(int s, int e)
{
    for (int i = s; i <= e; i++)
    {
        // 重い処理があるとする
        Thread.Sleep(1000);
        yield return i;
    }
}

実行結果

1
2
3

内部イテレータ

breakが使えないのでループを終了判定の渡し方を用意しておかないといけない。

static void Main(string[] args)
{
    DateTime d = DateTime.Now;
    f(1, 10, delegate(int i)
    {
        Console.WriteLine((DateTime.Now - d).Seconds.ToString());
        return (i == 3);
    });
    Console.ReadLine();
}

static void f(int s, int e, Func<int, bool> func)
{
    for (int i = s; i <= e; i++)
    {
        // 重い処理があるとする
        Thread.Sleep(1000);
        if (func(i)) { break; }
    }
}

実行結果

1
2
3