在编写自定义迭代器时,如何避免编译器生成抛出异常的Reset()方法?
本文关键字:抛出异常 Reset 方法 编译器 自定义 迭代器 何避免 | 更新日期: 2023-09-27 17:54:20
我编写了一个自定义迭代器来解决复杂的COM互操作问题。迭代器非常简单:
public IEnumerator GetEnumerator()
{
yield return DriveRates.driveSidereal;
yield return DriveRates.driveKing;
yield return DriveRates.driveLunar;
yield return DriveRates.driveSolar;
}
DriveRates
是一个enum。
我的理解是编译器应该把它变成一个状态机,它做到了,但是当客户端应用程序使用代码时,我得到这个异常:
<>之前系统。NotSupportedException:指定的方法不支持。在TiGra.Astronomy.AWRDriveSystem.TrackingRates.d__0.System.Collections.IEnumerator.Reset ()在System.Runtime.InteropServices.CustomMarshalers.EnumVariantViewOfEnumerator.Reset ()在System.Runtime.InteropServices.Marshal。ThrowExceptionForHRInternal(Int32 errorCode, IntPtr errorInfo)在System.Runtime.InteropServices.CustomMarshalers.EnumeratorViewOfEnumVariant.Reset ()[…客户端应用程序)之前查看dotPeek中编译器生成的代码,下面是生成的Reset()方法。
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
嗯,我想这解释了例外,但是……WWWHHHYYYYY吗?当然,在这种情况下,Reset不是不可能简单地重置状态机。是否有任何方法可以使编译器生成一个Reset()方法,不抛出?
不行。可以重置状态机的假设适用于您的简单情况,但请注意,您可以编写具有副作用的迭代器,并且编译器不能假设在一般情况下状态机是纯。因此,最安全的做法是直接禁用Reset
函数(顺便说一下,这个函数很少被使用,我认为它更像是一个设计错误,而不是一个有用的功能)。
你的代码最简单的解决方法是…
public IEnumerator GetEnumerator()
{
return new[] {
DriveRates.driveSidereal,
DriveRates.driveKing,
DriveRates.driveLunar,
DriveRates.driveSolar
}.GetEnumerator();
}
我假设DriveRates
中的值在枚举期间不会改变,在这种情况下代码不会产生相同的结果:这个版本是渴望。