yield return で、Reset() しようとしたら、例外が発生したので、メモ。
yield return を使って、1つづつ値を処理しようと思ったのですが、一般には次のような foreach, IEnumerator を使って、列挙することができます。
using System;
using System.Collections.Generic;
using System.Collections;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
MyClass mc = new MyClass();
foreach (string s in mc)
Console.WriteLine(s);
IEnumerator<string> e = mc.GetEnumerator();
while (e.MoveNext())
{
Console.WriteLine(e.Current);
} Console.ReadLine();
}
public class MyClass
{
public IEnumerator<string> GetEnumerator()
{
yield return “Hello1”;
yield return “Hello2”;
yield return “Hello3”;
yield return “Hello4”;
}
}
}
}
ある限られた要素を、無限に Enumerate できるようにしようと思って、yield return で与えられた Enumerable を Enumerate して、MoveNext()できなかったら、最初にReset()したが、Reset()のところで、NotSupportedException 例外となりました。
IEnumerator<string> col = mc.GetEnumerator();
for (int i = 0; i < 50; i++)
{
if (col.MoveNext() == false)
{
col.Reset(); // <<<<<<<<<<<<<< ここで NotSupportedException 例外
col.MoveNext();
}
Console.WriteLine(col.Current);
}
aetos さんのところに詳細に解説が載ってました。http://blogs.wankuma.com/shannon/archive/2007/07/10/84596.aspx
yield は Reset() のところまで実装していないので、当然リセットできないということですね。なお、これを回避するには、Reset()ではなく、Enumerator を取り直せば、繰り返しできる。
ある限られた要素を、無限に列挙するのは、あえてやるとすると、こんな感じ?
MyClass2 mc2 = new MyClass2();
for (int i = 0; i < 50; i++)
{
Console.WriteLine(mc2.GetNext());
}
public class MyClass2
{
string[] test = { “Hello1”, “Hello2”, “Hello3”, “Hello4”, “Hello5” };
static int i = -1;
public string GetNext()
{
if (++i >= test.Length)
i = 0;
return test[i];
}
}
neueccさんからの linq のコードを教えてもらった。なるほど~。有限回の繰り返しなら、シンプルでいいねー。
http://gyazo.com/6c17ca767c84e4f695a3f4420a66dba2
var array = new[] { “Hello1”, “Hello2” };
var query = Enumerable.Repeat(array, 2).SelectMany(xs=>xs);
foreach(var item in query)
Console.WriteLine(item);
コメントを残す