22

如果我逐步执行以下代码,则会跳过对 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;
}

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

4

1 回答 1

38

您实际上并没有使用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 章 - 这恰好是第一版中的免费章节 :)在此处获取。

于 2010-03-23T23:22:57.413 回答