You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

封装Span<Range>.Enumerator时抛出IndexOutOfRangeException问题

问题原因及解决办法

核心问题:只读值类型字段导致状态无法更新

Span<Range>.Enumerator是值类型(ref struct本质属于值类型范畴),而你把封装的枚举器字段标记为readonly。当调用MoveNext()时,因为字段是只读的,CLR会创建一个该枚举器的不可变副本执行方法——也就是说,你调用的MoveNext()其实是在副本上修改状态,原字段的枚举器根本没移动过。

这就导致了诡异的现象:MoveNext()返回true(副本的状态确实移动了),但你访问的是原只读字段的Current,而原枚举器还停留在初始无效状态,此时访问Current必然抛出IndexOutOfRangeException。

解决办法:移除readonly修饰符

只需要去掉_enumerator字段的readonly标记,让方法可以直接修改枚举器实例的状态:

public ref struct BasicEnumerator
{
    // 移除readonly修饰符
    private Span<Range>.Enumerator _enumerator;

    public Range Current => _enumerator.Current;

    public BasicEnumerator(Span<Range>.Enumerator enumerator)
    {
        _enumerator = enumerator;
    }

    public bool MoveNext() => _enumerator.MoveNext();

    public BasicEnumerator GetEnumerator() => this;
}

补充说明

直接使用Span<Range>.Enumerator时不会出问题,是因为此时枚举器是可变的局部变量,调用MoveNext()会直接修改自身状态,不会产生副本。而封装成只读字段后,值类型的拷贝特性加上只读限制,就触发了这个隐藏的坑。

内容的提问来源于stack exchange,提问作者killian-dtn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 21:57:14