Bing Chatに「C#でGOFのイテレータパターンを使ったサンプルコードを書いてください。」とお願いしてみた。

ネット・サービス コンピュータ

Chat-GPT4は有償らしいので、今のところ無償で利用できるMicrosoftのBing Chatを試してみました。
返ってきたソースコードは以下の通り。

using System;
using System.Collections;

// Aggregate
interface IAggregate
{
    IIterator CreateIterator();
}

// Iterator
interface IIterator
{
    bool HasNext();
    object Next();
}

// ConcreteAggregate
class ConcreteAggregate : IAggregate
{
    private ArrayList _items = new ArrayList();

    public IIterator CreateIterator()
    {
        return new ConcreteIterator(this);
    }

    public int Count => _items.Count;

    public object this[int index]
    {
        get => _items[index];
        set => _items.Insert(index, value);
    }
}

// ConcreteIterator
class ConcreteIterator : IIterator
{
    private ConcreteAggregate _aggregate;
    private int _current = 0;

    public ConcreteIterator(ConcreteAggregate aggregate)
    {
        _aggregate = aggregate;
    }

    public bool HasNext()
    {
        return _current < _aggregate.Count;
    }

    public object Next()
    {
        if (HasNext())
        {
            return _aggregate[_current++];
        }
        else
        {
            throw new InvalidOperationException();
        }
    }
}

class Program
{
    static void Main(string[] args)
    {
        var aggregate = new ConcreteAggregate();
        aggregate[0] = "Item A";
        aggregate[1] = "Item B";
        aggregate[2] = "Item C";

        var iterator = aggregate.CreateIterator();
        while (iterator.HasNext())
        {
            Console.WriteLine(iterator.Next());
        }
    }
}

consoleで実行するコードのようなのでプロジェクトを作成し、ソースコードをコピーして実行してみる。
結果

Item A
Item B
Item C

結果が返ってきました。問題なく実行できるコードのようです。

GOFのデザインパターンはいつかは勉強しようかと思い書籍を買い込んでページを開くのですが、具体的に適用できる事例と遭遇することが無いと中々モチベーションが維持できず毎回挫折してしまいます。特にイテレータパターンは、多くの言語系の標準ライブラリに組み込まれており、構造を勉強することは大変価値があるとは思うのですが、個人的に使うことはまずないかなと思います。

今回Bing Chatが実行可能なサンプルコードを書いてくれたので中身を確認したいと思います。

Aggregateインターフェイス


// Aggregate
interface IAggregate
{
    IIterator CreateIterator();
}

IIteratorオブジェクトを生成するCreateIterator()を定義しています。
インターフェイスですので継承して中身を実装することに成ります。

Iteratorインターフェイス

// Iterator
interface IIterator
{
    bool HasNext();
    object Next();
}

次の要素の有無を返すHasNext()メソッド、現在の要素を返し次の要素へ移動するNext()メソッドを定義しています。

ConcreteAggregateクラス

// ConcreteAggregate
class ConcreteAggregate : IAggregate
{
    private ArrayList _items = new ArrayList();

    public IIterator CreateIterator()
    {
        return new ConcreteIterator(this);
    }

    public int Count => _items.Count;

    public object this[int index]
    {
        get => _items[index];
        set => _items.Insert(index, value);
    }
}

Aggregateを継承し実装するクラスになります。
private ArrayList _items = new ArrayList();で配列をメンバーとして定義初期化しています。
ArrayListは初めて見ましたが、C#にテンプレートが導入される前から存在する可変長配列で要素の型はobjectのようです。要素を取り出して使う場合キャストが必須となります。List<string>に置き換えることが出来そうです。置き換えるとイテレータパターンのサンプルにならないのでダメかもしれません。

public IIterator CreateIterator()ではConcreteIteratorクラスのオブジェクトを生成して返しています。

public int Count => _items.Count;_itemsの要素数を返します。

public object this[int index]プロパティはindexで指定した_itemsの要素の読み書きをするプロパティ。プロパティを使っているあたりC#らしくて良いです。

ConcreteIteratorクラス

// ConcreteIterator
class ConcreteIterator : IIterator
{
    private ConcreteAggregate _aggregate;
    private int _current = 0;

    public ConcreteIterator(ConcreteAggregate aggregate)
    {
        _aggregate = aggregate;
    }

    public bool HasNext()
    {
        return _current < _aggregate.Count;
    }

    public object Next()
    {
        if (HasNext())
        {
            return _aggregate[_current++];
        }
        else
        {
            throw new InvalidOperationException();
        }
    }
}

Iteratorの実装部分。
private int _current = 0;で現在の要素のインデックスを保持しています。
HasNext()はループの終了条件に使われます。
Next()_currentが指し示す_aggregateの要素を返します。
この際_currentの値を加算することで次の要素に移動します。
_current++で加算されますが、_aggregateの要素にアクセスした後に処理されるようです。

Main()

これまで定義したクラスを組み合わせて、文字を格納した配列と、その要素に順番にアクセスするプログラムを実行しています。
ではこちらのパターンを実際使うかというと今のC#であればList<string>foreach()の組み合わせで十分ですので、使うことはないかなと思います。(そういえば昔C言語で可変長配列を自前で作成する際、似たようなコードを書いた記憶があります。)

ただ、GOFのデザインパターンは用語としての意味を理解していると、文書生成AIにコード作成を依頼する際、「C#でGOFの〇〇〇パターンを使ったサンプルコードを書いてください。」のような使い方が出来て便利だと思いました。

コメント