C# 语法问题IEnumerable<;T>;收益率法

C# 语法问题IEnumerable<;T>;收益率法,c#,yield-return,C#,Yield Return,以下是我的方法: static IEnumerable<DateTime> GetMonths(DateTime from, DateTime to) { // if logs is not uptodate TimeSpan logsMissingTimespan = to - from; if (logsMissingTimespan != new TimeSpan(0)) { return GetMonthsBetweenTwo

以下是我的方法:

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

一个方法要么是用迭代器块实现的,要么不是——所以要么所有的东西都是关于
收益率返回
收益率中断
,要么没有

然而,你不需要做任何特别的事情。原始的
GetMonthBetweenTwoDates
已经在
to==from
的位置工作,因为它永远不会进入while循环


另一方面,我觉得您使用
lastDate
很可疑,特别是,如果
from
恰好与
DateTime.MaxValue
在同一个月,它看起来会做一些不同的事情

因为您使用了单词
yield
,它现在希望该方法一次生成一个元素。它只能使用
yeild return
yield break
在每次迭代中返回一个元素


您应该使用
Enumerable.Empty()
而不是
产生中断

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

如果满足条件,则第一个示例直接返回
IEnumerable
,如果不满足条件,则返回null引用。第二个示例总是返回一个
IEnumerable
,但条件决定它是否有任何元素

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


如果您所关心的只是返回一个null引用,那么可以通过返回
Enumerable.Empty
而不是
null
使方法在语义上相同

在第一次检查时,您不需要屈服中断来结束迭代

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

如果它返回会更好,因为当前调用代码必须区分空结果和非空结果示例的可能重复是愚蠢的,这只是为了说明我的目的:-)@Florian:那么我建议你以后选择一个更好的示例:)认真地说,如果它能代表你真正想要做的事情,这会有所帮助,因为可能会有更好的方法。好吧,我会关注你的未来。即使我认为我永远不会使用stackoverflow提问,因为我很快就会收到一本非常好的书[1]:-)[1]@弗洛里安:乔恩没有提到的是,他的书只是一个复杂的人工智能的产物,从中获取答案;)
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>();
}
if (logsMissingTimespan == new TimeSpan(0))
{
    return null;
}    
return GetMonthsBetweenTwoDates(from, to);