语法问题 IEnumerable;使用yield返回的方法

发布于 2024-12-18 11:36:45 字数 1593 浏览 3 评论 0原文

这是我的方法:

static IEnumerable<DateTime> GetMonths(DateTime from, DateTime to)
{
    // if logs is not uptodate
    TimeSpan logsMissingTimespan = to - from;

    if (logsMissingTimespan != new TimeSpan(0))
    {
        return GetMonthsBetweenTwoDates(from, to);
    }

    return null; // Why this line ?
}

private static IEnumerable<DateTime> GetMonthsBetweenTwoDates(DateTime from, DateTime to)
{

    DateTime date = from;
    DateTime lastDate = DateTime.MaxValue;

    while (date < to)
    {
        if (lastDate.Month != date.Month)
        {
            lastDate = date;
            yield return lastDate;
        }
        date = date.AddDays(1);
    }
}

它工作正常,但我想我可以写一些更干净的东西,如下所示:

static IEnumerable<DateTime> GetMonths(DateTime from, DateTime to)
{
    TimeSpan logsMissingTimespan = to - from;

    if (logsMissingTimespan == new TimeSpan(0))
    {
        yield break;
    }

    return GetMonthsBetweenTwoDates(from, to);
}

但我有一条错误消息:

无法从迭代器返回值。使用yield return语句返回一个值,或者使用yield break结束迭代。

为什么我应该return null以及正确的语法是什么?

编辑:

所以,正确的方法是使用 Enumerable.Empty :

static IEnumerable<DateTime> GetMonths(DateTime from, DateTime to)
{
    // if logs is not uptodate
    TimeSpan logsMissingTimespan = to - from;

    if (logsMissingTimespan != new TimeSpan(0))
    {
        return GetMonthsBetweenTwoDates(from, to);
    }

    return Enumerable.Empty<DateTime>();
}

Here is my method :

static IEnumerable<DateTime> GetMonths(DateTime from, DateTime to)
{
    // if logs is not uptodate
    TimeSpan logsMissingTimespan = to - from;

    if (logsMissingTimespan != new TimeSpan(0))
    {
        return GetMonthsBetweenTwoDates(from, to);
    }

    return null; // Why this line ?
}

private static IEnumerable<DateTime> GetMonthsBetweenTwoDates(DateTime from, DateTime to)
{

    DateTime date = from;
    DateTime lastDate = DateTime.MaxValue;

    while (date < to)
    {
        if (lastDate.Month != date.Month)
        {
            lastDate = date;
            yield return lastDate;
        }
        date = date.AddDays(1);
    }
}

it works fine but I think I can write something cleaner like this :

static IEnumerable<DateTime> GetMonths(DateTime from, DateTime to)
{
    TimeSpan logsMissingTimespan = to - from;

    if (logsMissingTimespan == new TimeSpan(0))
    {
        yield break;
    }

    return GetMonthsBetweenTwoDates(from, to);
}

But I have an error message :

Cannot return a value from an iterator. Use the yield return statement to return a value, or yield break to end the iteration.

Why should I have a return null and what is the correct syntax ?

EDIT :

So, the correct way is to use Enumerable.Empty :

static IEnumerable<DateTime> GetMonths(DateTime from, DateTime to)
{
    // if logs is not uptodate
    TimeSpan logsMissingTimespan = to - from;

    if (logsMissingTimespan != new TimeSpan(0))
    {
        return GetMonthsBetweenTwoDates(from, to);
    }

    return Enumerable.Empty<DateTime>();
}

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

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

发布评论

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

评论(4

分分钟 2024-12-25 11:36:46

您不需要在第一次检查时使用 Yield Break 来结束迭代。

if (logsMissingTimespan == new TimeSpan(0))
{
    return null;
}    
return GetMonthsBetweenTwoDates(from, to);

you don't need yield break to end the iteration at your first check.

if (logsMissingTimespan == new TimeSpan(0))
{
    return null;
}    
return GetMonthsBetweenTwoDates(from, to);
零度℉ 2024-12-25 11:36:45

因为您使用了 yield 这个词,所以它现在期望该方法一次yield一个元素。每次迭代只能使用 yield returnyield break 返回一个元素。

您应该使用 Enumerable.Empty(); 而不是 yield break

Because you have used the word yield it now expects the method to yield one element at a time. It must only use yeild return or yield break to return one element per iteration.

You should use Enumerable.Empty<DateTime>(); instead of yield break.

我是男神闪亮亮 2024-12-25 11:36:45

前两个示例的形式会产生不同类型的输出。

如果满足条件,您的第一个示例将直接返回 IEnumerable ,如果不满足,则返回 null 引用。您的第二个示例始终返回一个IEnumerable,但条件确定它是否包含任何元素。

第二个示例是通过使用迭代器块来完成的。 C# 编译器使用 yield 语法将您编写的函数转换为实现 IEnumerable 的自定义(隐藏)类型和实现 的类型>IEnumerator。这些类型实现必要的状态机,以实现(希望)您放入函数中的逻辑。正因为如此,你不能混合范例;您必须从函数返回 IEnumerable 实例(并且根本不使用 yield ),或者所有内容都必须通过 yield 返回代码>.

如果您只关心返回 null 引用这一事实,则可以通过返回 Enumerable.Empty 而不是 null 来使这些方法在语义上相同代码>.

The forms of your first two examples produce different sorts of output.

Your first example returns an IEnumerable<T> directly if the condition is satisfied, and a null reference if it is not. Your second example always returns an IEnumerable<T>, but the condition determines whether or not it has any elements.

The second example is done by using an iterator block. The yield syntax is used by the C# compiler to turn the function that you wrote into a custom (hidden) type that implements IEnumerable<T> and a type that implements IEnumerator<T>. These types implement the necessary state machines in order to achieve (hopefully) the logic that you've placed into the function. Because of this, you cannot mix paradigms; you must either return an instance of IEnumerable<T> from the function (and not use yield anywhere at all), or everything must be returned via yield.

If all you're concerned with is the fact that you're returning a null reference, you could make the methods semantically the same by returning Enumerable.Empty<DateTime> rather than null.

并安 2024-12-25 11:36:45

方法要么是用迭代器块实现的,要么不是——所以要么一切都以yield returnyield break表示,要么都没有这是。

但是,您不需要做任何特别的事情。您原来的 GetMonthsBetweenTwoDates 已经可以在 to == from 处工作,因为它永远不会进入 while 循环。

另一方面,您对 lastDate 的使用对我来说看起来很可疑 - 特别是,如果 from 碰巧在同一个月,它看起来会做不同的事情DateTime.MaxValue

A method is either implemented with an iterator block or it's not - so either everything is in terms of yield return and yield break, or none of it is.

However, you don't need to do anything special. Your original GetMonthsBetweenTwoDates already works where to == from, because it'll never enter the while loop.

On the other hand, your use of lastDate looks suspicious to me - in particular, it looks like it'll do something different if from happens to be in the same month as DateTime.MaxValue.

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