C# 在迭代器中作为返回的自定义类
我有一个扩展方法,它使用DateTimes遍历POCO类的列表。然后,此方法将重叠或落在彼此的公差时间跨度内的明细表组合在一起。这个很好用 然而,我需要的一部分是获得一个组合项目的ID列表(来自DB),以供以后参考。我试图转换扩展方法以返回自定义类,但出现以下错误:C# 在迭代器中作为返回的自定义类,c#,C#,我有一个扩展方法,它使用DateTimes遍历POCO类的列表。然后,此方法将重叠或落在彼此的公差时间跨度内的明细表组合在一起。这个很好用 然而,我需要的一部分是获得一个组合项目的ID列表(来自DB),以供以后参考。我试图转换扩展方法以返回自定义类,但出现以下错误: Error CS1624 The body of 'Extensions.Combine(CombinedSchedules)' cannot be an iterator block because 'CombinedSch
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;
}
}
公共静态组合计划合并(此组合计划项目)
{
使用(IEnumerator枚举器=items.Schedules.GetEnumerator())
{
如果(!enumerator.MoveNext())
{
屈服断裂;
}
var previous=枚举数。当前值;
while(枚举数.MoveNext())
{
var next=枚举数.Current;
if(TryCombine(上一个、下一个、外var组合))
{
项目.包括附表.TryAdd(先前的.Id);
先前=合并;
持续
}
以前的收益率;
上一个=下一个;
}
以前的收益率;
}
}
以下是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
}
公共类组合计划:IEnumerable,IDisposable
{
布尔=假;
//实例化一个SafeHandle实例。
SafeHandle=新的SafeFileHandle(IntPtr.Zero,true);
公共列表计划{get;set;}
公共列表IncludedSchedules{get;set;}
公共IEnumerator GetEnumerator()
{
返回Schedules.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
返回Schedules.GetEnumerator();
}
#区域IDisposable支持
private bool disposedValue=false;//用于检测冗余调用
受保护的虚拟void Dispose(bool disposing)
{
如果(!disposedValue)
{
如果(处置)
{
//TODO:处置托管状态(托管对象)。
}
//TODO:释放非托管资源(非托管对象)并覆盖下面的终结器。
//TODO:将大字段设置为null。
disposedValue=true;
}
}
//TODO:仅当上面的Dispose(bool disposing)具有释放非托管资源的代码时,才重写终结器。
//~CombinedSchedules(){
////不要更改此代码。请将清理代码放入上面的Dispose(bool disposing)中。
//处置(虚假);
// }
//添加此代码是为了正确实现一次性模式。
公共空间处置()
{
//不要更改此代码。请将清理代码放入上面的Dispose(bool disposing)中。
处置(真实);
//TODO:如果上面覆盖了终结器,则取消对以下行的注释。
//总干事(本);
}
#端区
}
我怎样才能取回所有我需要的东西,以便以后参考组合时间表列表?提前谢谢 如果
Combine
方法应该返回一个新的CombinedSchedules
对象,我建议将其从迭代器方法转换为“普通”扩展方法,大致遵循以下逻辑:
扩展方法将枚举并组合来自提供的原始源CombinedSchedules对象的ScheduleDto实例,并在此过程中构建一个新的IncludedSchedules集合。使用合并的ScheduleDto和新的IncludedSchedules集合,将创建并返回一个新的CombinedSchedules对象。在方法中使用
收益返回
或收益中断
时,它必须返回IEnumerable
、IEnumerator
或通用版本。这里发生的是C编译器将您的方法重建为实现IEnumerator
和IEnumerable
的对象的MoveNext
方法
编译器不知道如何构建列表、字典、字符串或任何其他也实现了IEnumerable
的类型
现在,您想要的特性是可能的,我们知道这是可能的,因为C#7对async
方法是这样做的。在以前的版本中,async
方法只能返回Task
、void
或Task
,原因与此相同,但在C#7中,编译器团队添加了提供您自己的“任务生成器”类的功能
理论上,编译器团队可以对迭代器块做同样的事情,但总体感觉对该功能的需求不大
那么,您最好选择以下两种策略之一:
- 坚持使用生成的方法,然后编写另一个扩展方法,将序列转换为数据类型。请参阅
,或ToList
或ToDictionary
或任何其他方法,这些方法采用一个序列并返回从该序列派生的完全不同的数据结构。如果经常需要从序列构造摘要对象,则此技术非常有用。调用站点将是string.Join
其中combined.GetSchedules().Combine()
接受GetSchedules()
并返回CombinedSchedule
和IEnumerable
接受Combine()
并返回IEnumerable
CombinedSchedule
- 停止屈服;创建一个CombinedScheduleBuilder对象,并在生成的任何地方调用生成器上的Add方法。(屈服断裂变为返回。)方法所做的最后一件事是返回构建器构建的内容。这对于简单地将一个对象转换为另一个对象的情况非常有用,这似乎很适合您的场景。(这基本上是elgonzo的答案提出的想法。)