0Pricing
C# Academy · レッスン

yield returnによるイテレーターメソッド

一度に1要素ずつシーケンスを生成します。

「yield returnによるイテレーターメソッド」はCoddyKit上の無料C# Academyレッスンです。 これはレッスン1/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはC# Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 C# Academyコースには全4レッスンが含まれています。

イテレーターメソッドとは

イテレーターメソッドは、yield return を使って値を一度に 1 つずつ生成するメソッドです。コンパイラーがこれをステートマシンに変換するため、自分でリストを構築して管理する必要はありません。

最初の yield return

各 yield return は 1 つの値を呼び出し側に返し、メソッドを一時停止します。次の反復では、その文の直後から実行が再開されます。

using System;
using System.Collections.Generic;

public class Program
{
    static IEnumerable<int> FirstThree()
    {
        yield return 1;
        yield return 2;
        yield return 3;
    }

    public static void Main()
    {
        foreach (var n in FirstThree())
            Console.WriteLine(n);
    }
}

ループ内の yield return

ほとんどのイテレーターは、ループ内で値を生成します。ここでは、コレクションを一度も割り当てずに、最初の count 個の偶数を生成します。

using System;
using System.Collections.Generic;

public class Program
{
    static IEnumerable<int> Evens(int count)
    {
        for (int i = 0; i < count; i++)
            yield return i * 2;
    }

    public static void Main()
    {
        foreach (var n in Evens(5))
            Console.WriteLine(n);
    }
}

メソッドは IEnumerable を返す

イテレーターメソッドは、IEnumerable<T> または IEnumerator<T>(あるいは非ジェネリック版)を返す必要があります。値を伴う return は記述せず、yield return だけを使用します。

using System;
using System.Collections.Generic;

public class Program
{
    static IEnumerable<string> Greetings()
    {
        yield return "hello";
        yield return "hi";
        yield return "hey";
    }

    public static void Main()
    {
        foreach (var g in Greetings())
            Console.WriteLine(g);
    }
}

実行は一時停止と再開を繰り返す

yield の間の状態は自動的に保持されます。ローカル変数は一時停止している間も値を保持するため、累計値を生成する処理を簡単に記述できます。

using System;
using System.Collections.Generic;

public class Program
{
    static IEnumerable<int> RunningTotal(IEnumerable<int> nums)
    {
        int total = 0;
        foreach (var n in nums)
        {
            total += n;
            yield return total;
        }
    }

    public static void Main()
    {
        foreach (var t in RunningTotal(new[] { 1, 2, 3, 4 }))
            Console.WriteLine(t);
    }
}

無限シーケンスを生成する

値は必要になったときに生成されるため、イテレーターでは無限シーケンスも安全に表現できます。値の取得をいつ停止するかは呼び出し側が決めます。

using System;
using System.Collections.Generic;

public class Program
{
    static IEnumerable<int> Naturals()
    {
        int i = 1;
        while (true) yield return i++;
    }

    public static void Main()
    {
        int taken = 0;
        foreach (var n in Naturals())
        {
            Console.WriteLine(n);
            if (++taken == 5) break;
        }
    }
}

入力シーケンスを変換する

イテレーターはパイプラインの構築に適しています。1 つのシーケンスから項目を読み取り、変換して、結果を遅延的に生成できます。

using System;
using System.Collections.Generic;

public class Program
{
    static IEnumerable<string> Labelled(IEnumerable<int> nums)
    {
        foreach (var n in nums)
            yield return "item-" + n;
    }

    public static void Main()
    {
        foreach (var s in Labelled(new[] { 10, 20, 30 }))
            Console.WriteLine(s);
    }
}

イテレーターでフィルター処理する

フィルター処理では、必要な項目だけを生成します。スキップされた項目は生成されないため、後続のコードからは見えません。

using System;
using System.Collections.Generic;

public class Program
{
    static IEnumerable<int> OnlyPositive(IEnumerable<int> nums)
    {
        foreach (var n in nums)
            if (n > 0) yield return n;
    }

    public static void Main()
    {
        foreach (var n in OnlyPositive(new[] { -2, 5, -1, 8 }))
            Console.WriteLine(n);
    }
}

コンパイラーがステートマシンを構築する

内部では、コンパイラーがイテレーターを IEnumerator<T> を実装するクラスに書き換え、非公開の状態フィールドと Current の値を追跡します。この仕組みはすべて自動的に用意されます。

using System;
using System.Collections.Generic;

public class Program
{
    static IEnumerable<char> Letters()
    {
        yield return 'a';
        yield return 'b';
        yield return 'c';
    }

    public static void Main()
    {
        IEnumerator<char> e = Letters().GetEnumerator();
        while (e.MoveNext())
            Console.WriteLine(e.Current);
    }
}

複数のイテレーターを組み合わせる

各イテレーターが IEnumerable<T> を返すため、イテレーターは自然につなげられます。1 つのイテレーターの出力を次のイテレーターに渡して、読みやすいパイプラインを構築できます。

using System;
using System.Collections.Generic;

public class Program
{
    static IEnumerable<int> Range(int start, int count)
    {
        for (int i = 0; i < count; i++) yield return start + i;
    }
    static IEnumerable<int> Squares(IEnumerable<int> nums)
    {
        foreach (var n in nums) yield return n * n;
    }

    public static void Main()
    {
        foreach (var n in Squares(Range(1, 4)))
            Console.WriteLine(n);
    }
}

自分で試す

入力シーケンスを固定サイズのチャンクに分割するイテレーターを書いてみましょう。必要に応じてリストを生成することで、1 つの簡潔なイテレーターにどれだけのロジックを収められるかを確認できます。

using System;
using System.Collections.Generic;

public class Program
{
    static IEnumerable<List<int>> Batch(IEnumerable<int> source, int size)
    {
        var bucket = new List<int>();
        foreach (var n in source)
        {
            bucket.Add(n);
            if (bucket.Count == size) { yield return bucket; bucket = new List<int>(); }
        }
        if (bucket.Count > 0) yield return bucket;
    }

    public static void Main()
    {
        foreach (var group in Batch(new[] { 1, 2, 3, 4, 5 }, 2))
            Console.WriteLine(string.Join(",", group));
    }
}

クイックチェック

イテレーターメソッドの動作を思い出してみましょう。

まとめ

イテレーターメソッドは yield return を使って、必要に応じてシーケンスを生成します。

  • メソッドは IEnumerable<T> または IEnumerator<T> を返します。
  • 各 yield return は 1 つの値を生成して一時停止し、ローカル状態を保持します。
  • 無限シーケンスも安全に表現できます。
  • ステートマシンはコンパイラーが生成します。

よくある質問

「yield returnによるイテレーターメソッド」レッスンは無料ですか?

はい。「yield returnによるイテレーターメソッド」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、C# Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 C# Academyコースには全4レッスンが含まれています。

「yield returnによるイテレーターメソッド」で何を学びますか?

一度に1要素ずつシーケンスを生成します。 ブラウザで直接実行するハンズオンコードでC# Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

C# Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのC# Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン1/4です。

「yield returnによるイテレーターメソッド」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このC# Academyレッスンでコードを書いて実行できますか?

はい。すべてのC# Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. yield returnによるイテレーターメソッド
  2. yield breakと早期終了
  3. 遅延評価のセマンティクス
  4. カスタム列挙可能型
← C# Academyに戻る