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の〇〇〇パターンを使ったサンプルコードを書いてください。」のような使い方が出来て便利だと思いました。


コメント