嵌套方法中的C#yield

时间:2010-03-23 23:20:25

标签: c# ienumerable yield

如果我单步执行以下代码,则会跳过对ReturnOne()的调用。

static IEnumerable<int> OneThroughFive()
{
    ReturnOne();
    yield return 2;
    yield return 3;
    yield return 4;
    yield return 5;
}

static IEnumerator<int> ReturnOne()
{
    yield return 1;
}

我只能假设编译器正在剥离它,因为我正在做的是无效的。我希望能够将我的枚举分离成各种方法。这可能吗?

1 个答案:

答案 0 :(得分:30)

您实际上并未使用ReturnOne的结果。您正在调用该方法,并忽略返回值...这意味着您实际上从未看到任何代码正在运行。你可以这样做:

static IEnumerable<int> OneThroughFive()
{
    foreach (int x in ReturnOne())
    {
        yield x;
    }
    yield return 2;
    yield return 3;
    yield return 4;
    yield return 5;
}

C#没有(目前至少:)有一种“全部收益”结构。

你没有进入它的事实与你在迭代器块中有一个调用的事实无关 - 只是在你开始使用结果之前迭代器块的代码,没有代码运行。这就是为什么你需要将参数验证与屈服分开。例如,请考虑以下代码:

public IEnumerator<string> ReturnSubstrings(string x)
{
    if (x == null)
    {
         throw ArgumentNullException();
    }
    for (int i = 0; i < x.Length; i++)
    {
         yield return x.Substring(i);
    }
}
...
ReturnSubstring(null); // No exception thrown

你需要这样写:

public IEnumerator<string> ReturnSubstrings(string x)
{
    if (x == null)
    {
         throw ArgumentNullException();
    }
    return ReturnSubstringsImpl(x);
}

private IEnumerator<string> ReturnSubstringsImpl(string x)
{
    for (int i = 0; i < x.Length; i++)
    {
         yield return x.Substring(i);
    }
}

有关详细信息,请阅读深度C#的第6章 - 这恰好是第一版中的免费章节:) Grab it here