C# · 12月 26, 2021

c# – 语法问题使用yield return的IEnumerable方法

这是我的方法: 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.