UnityVisualNovel (16-3) を進める をおこなううで、 csharp の IEnumerator と IEnumerable がわからなかったので調べます。
IEnumerable
public interface IEnumerable<out T> : IEnumerable
{
IEnumerator<T> GetEnumerator();
}
IEnumerator を公開するだけのインターフェースです。
foreach は IEnumerable を受け取ることができます。 これは糖衣構文であり、 foreach は IEnumerable から IEnumerator を取り出して MoveNext で要素を取得しています。
IEnumerator
https://qiita.com/dj_kusuha/items/2048391d821cb94fa489 https://kakovail.info/entry/advent_2023_cs#google_vignette
IEnumerator は System.Collections namespace で定義されているインターフェースです。 列挙子に関するインターフェースであり、順番にものを取得する、ときに使えます。
public interface IEnumerator
{
object Current { get; }
bool MoveNext();
void Reset();
}
while に IEnumerator.MoveNext() を与えることでイテレータを順番に回す、が行えます。
サンプルとして下記を実装してみました。
List<T>
は IEnumerable を実装しているため GetEnumerator で IEnumerator を返せます。
ここで、受け取り方として 3 つサンプル実装しています。
珍しいのが List<T>.Enumerator
であり、これは partial struct です。
効率がよいようです。
MoveNext(), Current で反復処理を行えます。
List<string> alphabets = new List<string> { "a", "b", "c" };
// List<string> は IEnumerable を実装している
// そのため GetEnumerator() で IEnumerator が得られる
// List<T>.Enumerator は List<T> 配下で partial struct として定義されている構造体
// そのまま IEnumeator として呼び出すよりも効率よくなっている
List<string>.Enumerator enumerator = alphabets.GetEnumerator();
// IEnumerator としても受け取れる
IEnumerator enumerator2 = alphabets.GetEnumerator();
// IEnumerator<T> としても受け取れる
IEnumerator<string> enumerator3 = alphabets.GetEnumerator();
// IEnumerator で Move
while (enumerator.MoveNext())
{
enumerator.Current;
}
public partial struct Enumerator : System.Collections.Generic.IEnumerator<T>, System.Collections.IEnumerator, System.IDisposable
{
private object _dummy;
public T Current { get { throw null; } }
object System.Collections.IEnumerator.Current { get { throw null; } }
public void Dispose() { }
public bool MoveNext() { throw null; }
void System.Collections.IEnumerator.Reset() { }
}