在编写自定义迭代器时,如何避免编译器生成抛出异常的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()方法?

不行。可以重置状态机的假设适用于您的简单情况,但请注意,您可以编写具有副作用的迭代器,并且编译器不能假设在一般情况下状态机是。因此,最安全的做法是直接禁用Reset函数(顺便说一下,这个函数很少被使用,我认为它更像是一个设计错误,而不是一个有用的功能)。

你的代码最简单的解决方法是…

public IEnumerator GetEnumerator()
{
    return new[] {
        DriveRates.driveSidereal,
        DriveRates.driveKing,
        DriveRates.driveLunar,
        DriveRates.driveSolar
    }.GetEnumerator();
}

我假设DriveRates中的值在枚举期间不会改变,在这种情况下代码不会产生相同的结果:这个版本是渴望