我有一个扩展方法,该方法用DateTimes遍历POCO类的列表。然后,此方法组合了彼此重叠或落入公差时间范围内的计划。效果很好!
但是,我的部分需求是同时获取(合并自数据库的)ID列表,以供以后参考。我尝试将扩展方法转换为返回自定义类,但出现以下错误:
Error CS1624 The body of 'Extensions.Combine(CombinedSchedules)' cannot be an iterator block because 'CombinedSchedules' is not an iterator interface type
这是我的扩展方法:
public static CombinedSchedules Combine(this CombinedSchedules items)
{
using (IEnumerator<ScheduleDto> enumerator = items.Schedules.GetEnumerator())
{
if (!enumerator.MoveNext())
{
yield break;
}
var previous = enumerator.Current;
while (enumerator.MoveNext())
{
var next = enumerator.Current;
if (TryCombine(previous, next, out var combined))
{
items.IncludedSchedules.TryAdd(previous.Id);
previous = combined;
continue;
}
yield return previous;
previous = next;
}
yield return previous;
}
}
这是CombinedSchedules类:
public class CombinedSchedules : IEnumerable<ScheduleDto>, IDisposable
{
bool disposed = false;
// Instantiate a SafeHandle instance.
SafeHandle handle = new SafeFileHandle(IntPtr.Zero, true);
public List<ScheduleDto> Schedules { get; set; }
public List<int> IncludedSchedules { get; set; }
public IEnumerator GetEnumerator()
{
return Schedules.GetEnumerator();
}
IEnumerator<ScheduleDto> IEnumerable<ScheduleDto>.GetEnumerator()
{
return Schedules.GetEnumerator();
}
#region IDisposable Support
private bool disposedValue = false; // To detect redundant calls
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
// TODO: dispose managed state (managed objects).
}
// TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
// TODO: set large fields to null.
disposedValue = true;
}
}
// TODO: override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources.
// ~CombinedSchedules() {
// // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
// Dispose(false);
// }
// This code added to correctly implement the disposable pattern.
public void Dispose()
{
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
Dispose(true);
// TODO: uncomment the following line if the finalizer is overridden above.
// GC.SuppressFinalize(this);
}
#endregion
}
我该如何取回我需要的所有东西,以便以后参考组合时间表的列表?预先感谢!
答案 0 :(得分:4)
在方法中使用yield return
或yield break
时,它必须返回IEnumerable
,IEnumerator
或通用版本。这里发生的是C#编译器将您的方法重建为实现MoveNext
和IEnumerator
的对象的IEnumerable
方法。
编译器不知道如何构建列表,字典,字符串或任何其他也实现IEnumerable
的类型。
现在,您想要的功能是 possible ,并且我们知道这是可能的,因为C#7对async
方法使用了该功能。在以前的版本中,出于相同的原因,async
方法只能返回Task
,void
或Task<T>
,但是在C#7中,编译器团队添加了提供自己的功能。 “任务构建器”类。
理论上,编译器团队可以对迭代器块执行相同的操作,但总体感觉是对该功能的需求不大。
您最好的选择是选择以下两种策略之一:
ToList
或ToDictionary
或string.Join
或采用序列并返回从该序列派生的完全不同的数据结构的任何其他方法。如果您经常需要从序列中构造摘要对象,则此技术很有用。呼叫站点将是combined.GetSchedules().Combine()
,其中GetSchedules()
接受CombinedSchedule
并返回IEnumerable<Schedule>
,而Combine()
接受IEnumerable<Schedule>
并返回CombinedSchedule
。 / li>
答案 1 :(得分:2)
如果Combine
方法应返回一个新的CombinedSchedules
对象,我建议将其从迭代器方法转换为“常规”扩展方法,或多或少遵循以下大致概述的逻辑: / p>
扩展方法将枚举并合并提供的原始源 CombinedSchedules 对象中的 ScheduleDto 实例,并同时构建一个新的 IncludedSchedules 集合方式。使用合并的 ScheduleDto 和新的 IncludedSchedules 集合,将创建并返回一个新的 CombinedSchedules 对象。