C# 嵌套方法中的yield

发布于 2024-08-25 23:00:41 字数 342 浏览 8 评论 0原文

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

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

If I step through the following code the call to ReturnOne() is skipped.

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

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

I can only assume the compiler is stripping it out because what I'm doing is not valid. I'd like the ability to isolate my enumeration into various methods. Is this possible?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

吲‖鸣 2024-09-01 23:00:41

您实际上并未使用 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#(至少目前:)没有某种“yield all”构造。

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

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 章 - 这恰好是第一版中的免费章节 :) 在这里获取

You're not actually using the result of ReturnOne. You're calling the method, and ignoring the return value... which means you'd never actually see any of your code being run. You can do it like this:

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

C# doesn't (currently at least :) have a sort of "yield all" construct.

The fact that you're not getting to step into it has nothing to do with the fact that you've got a call within an iterator block - it's just that until you start using the result of an iterator block, none of the code runs. That's why you need to separate out argument validation from yielding. For example, consider this code:

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

You need to write it like this:

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);
    }
}

For more details, read chapter 6 of C# in Depth - which happens to be a free chapter in the first edition :) Grab it here.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文