使用yield时增加IEnumerator / IEnumerable

时间:2012-10-27 23:17:48

标签: c# iterator ienumerable

我试图通过集合产生迭代,如果集合为空,则调用一个将获得下一组结果的increment方法。当增量表示没有更多结果时,则产生中断;

我不能使用(我认为)带有MoveNext()等的标准IEnumerator,因为increment方法返回两种不同类型的数据。

我在下面尝试了一个例子,但是在一次尝试后就停止了。我希望有一个更容易的方法(或者至少可能只是我有一个错误)。

static void Main(string[] args)
{
    var query = new Query();

    foreach(var s in query.Q1())
    {
        Console.WriteLine(s);
    }

    foreach (var s in query.Q2())
    {
        Console.WriteLine(s);
    }

    Console.ReadLine();
}

public class Query
{
    int i = 0;
    bool complete;
    List<string> q1 = new List<string>();
    List<string> q2 = new List<string>();

    public IEnumerable<string> Q1()
    {
        if (complete)
        {
            yield break;
        }
        if (!q1.Any() && !complete)
        {
            Increment();
        }
        if (q1.Any())
        {
            foreach (var s in q1)
            {
                yield return s;
            }
        }
    }

    public IEnumerable<string> Q2()
    {
        if (complete)
        {
            yield break;
        }
        if (!q2.Any() && !complete)
        {
            Increment();
        }
        if (q2.Any())
        {
            foreach (var s in q2)
            {
                yield return s;
            }
        }
    }

    void Increment()
    {
        if (i < 10)
        {
                    // simulate getting two types of data back (parent and two children) from datasource
            q1.Add((1 * (i + 1)).ToString());
            q2.Add("A: " + (1 * (i + 1)).ToString());
            q2.Add("B: " + (1 * (i + 1)).ToString());

            i++;
        }
        else
        {
            complete = true;
        }
    }
}

结果:

1
A: 1
B: 1

关于更好地做这件事或我出错的方法的任何想法?

修改

这是我的粗略和准备好的修复:

public IEnumerable<string> Q1()
{
    var index = 0;

    if (!complete)
    {
        while (!complete)
        {
            var count = q1.Count();

            if (index + 1 == count)
            {
                for (var x = index; index < count; index++)
                {
                    yield return q1[index];
                }
            }
            else
            {
                Increment();
            }
        }
    }
    else
    {
        foreach (var s in q1)
        {
            yield return s;
        }
    }
}

1 个答案:

答案 0 :(得分:1)

您只向q2列表添加元素。因此,当您调用Q1迭代器时,您将在检查

后退出它
if (q1.Any())

当你调用Q2迭代器时,你会在

之后退出它
if (q2.Any())
{
     foreach (var s in q2)
     {
         yield return s;
     }
}

这个foreach循环只执行一次,它只返回三个项目,这些项目在q2迭代器中的单Increment次调用期间添加到Q1

目前还不是很清楚你想要实现什么,但是这里可以使用循环来生成迭代器的返回值

public IEnumerable<string> Q2()
{
    for (int i = 1; i <= 10; i++) // start from 1
    {
        yield return i.ToString(); // do not multiply by 1
        yield return "A: " + i;    // .ToString() is not necessary 
        yield return "B: " + i;
    }
}