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

C#如何序列化/反序列化yield函数生成的IEnumerator?

序列化编译器生成的yield迭代器(IEnumerator)问题

需求说明

  • 需要实现yield关键字生成的IEnumerator的序列化与反序列化,要求能在任意迭代阶段保存状态,不能强制生成所有迭代值(避免触发不必要的游戏更新逻辑)
  • 核心目标是开发类似Nick Gravelyn《The magic of yield》的小型游戏引擎:每个GameElement通过迭代器描述行为,实现脚本的中断与续跑;现在要为引擎添加多人联机层,因此需要跨机器传输迭代器的状态

首次尝试:直接序列化接口

尝试直接用System.Text.Json序列化迭代器,代码如下:

using System;
using System.Collections.Generic;
using System.Text.Json;

namespace SerializeTest
{
    class Program
    {
        public static IEnumerator<int> CountTo(int end)
        {
            for(int i = 1; i <= end; i++) 
            {
                Console.WriteLine("i = " + i);
                yield return i;
            }
        }

        static void Main(string[] args)
        {
            IEnumerator<int> e = CountTo(5);
            string json = JsonSerializer.Serialize(e);
            Console.WriteLine(json);
            var f = JsonSerializer.Deserialize<IEnumerator<int>> (json); // 崩溃:无法反序列化接口

            while (f.MoveNext());
        }
    }
}

问题:反序列化时直接崩溃,因为IEnumerator<int>是接口,序列化器无法实例化接口类型。

第二次尝试:通过反射指定编译器生成的具体类型

已知yield会由编译器生成匿名类(比如SerializeTest.Program+<CountTo>d__0),尝试通过反射获取该类型并调用泛型反序列化方法,代码如下:

using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text.Json;

namespace SerializeTest
{
    class Program
    {
        public static IEnumerator<int> CountTo(int end)
        {
            for(int i = 1; i <= end; i++) 
            {
                Console.WriteLine("i = " + i);
                yield return i;
            }
        }

        public static T Deserialize<T>(string json) => JsonSerializer.Deserialize<T>(json); // 依然崩溃

        static void Main(string[] args)
        {
            IEnumerator<int> e = CountTo(5);

            string json = JsonSerializer.Serialize(e);
            Console.WriteLine(json);

            Type eType = e.GetType();
            MethodInfo method = typeof(Program).GetMethod("Deserialize");
            MethodInfo genericMethod = method.MakeGenericMethod(eType);

            object fObj = genericMethod.Invoke(null, new object[] { json });
            var f = (IEnumerator<int>)fObj;
            while (f.MoveNext()) ;
        }
    }
}

错误信息:

System.InvalidOperationException : 'Each parameter in constructor 'Void .ctor(Int32)' on type 'SerializeTest.Program+<CountTo>d__0' must bind to an object property or field on deserialization. Each parameter name must match with a property or field on the object. The match can be case-insensitive.'

问题:编译器生成的迭代器类的构造函数参数无法与序列化后的属性/字段对应绑定,导致反序列化失败。

后续需求

  • 序列化格式不限(JSON、XML等均可),只要能跨机器传输并恢复迭代器状态
  • 希望找到可行的实现方案,哪怕可行性较低

内容的提问来源于stack exchange,提问作者Thomas

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 15:25:19