这是我的方法:
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); }
但是我有一条错误消息:
Cannot return a value from an iterator. Use the yield return statement to return a value,or yield break to end the iteration.
为什么我应该返回null并且语法正确?
编辑:
所以,正确的方法是使用Enumerable.Empty:
static IEnumerable<DateTime> GetMonths(DateTime from,to); } return Enumerable.Empty<DateTime>(); }
解决方法
前两个示例的形式产生不同类型的输出.
您的第一个示例返回IEnumerable< T>如果条件满足则直接,如果不满足则为空引用.您的第二个示例始终返回IEnumerable< T>,但条件确定它是否具有任何元素.
第二个例子是使用迭代器块完成的. C#编译器使用yield语法将您编写的函数转换为实现IEnumerable< T>的自定义(隐藏)类型.和实现IEnumerator< T>的类型.这些类型实现了必要的状态机,以实现(希望)您放入函数的逻辑.因此,你不能混淆范式;你必须要么返回IEnumerable< T>的实例.来自函数(并且根本不使用yield),或者必须通过yield返回所有内容.
如果你所关心的是你正在返回一个空引用的事实,你可以通过返回Enumerable.Empty< DateTime>来使方法在语义上相同.而不是null.