为何JsonElement.ArrayEnumerator需同时实现IEnumerator与IEnumerable?
为什么JsonElement.ArrayEnumerator要在IEnumerator基础上实现IEnumerable?
这种设计主要是适配JsonElement自身特性,同时提升API易用性,具体原因如下:
- 让枚举器直接支持foreach遍历:调用
JsonElement.EnumerateArray()返回的ArrayEnumerator可以直接放进foreach循环使用,不用额外包装成集合。如果它只实现IEnumerator,你没法直接foreach它,得手动写MoveNext()和Current的逻辑,或塞进其他IEnumerable容器,会增加使用成本。 - 支持多次遍历数据源:
JsonElement是只读结构,普通枚举器遍历完就没法重置。现在枚举器实现IEnumerable后,每次调用GetEnumerator()都会生成全新的枚举器实例,能从头遍历数据源,这样你可以多次foreach同一个ArrayEnumerator对象(本质是每次生成新遍历器)。 - 适配JsonElement的轻量化解析特性:和数组、List不同,
JsonElement不是直接持有内存元素集合的对象,它是JSON文档的解析视图,遍历依赖枚举器维护解析状态。把枚举器设计成同时实现IEnumerable,相当于把“可遍历数据源”和“遍历状态”合并到同一对象,符合JSON解析的轻量化需求——不用额外创建专门的IEnumerable容器包装枚举逻辑。
而数组、List的数据源本身已经是IEnumerable,枚举器只是单纯的状态对象,用户通常直接foreach数据源而非枚举器,自然不需要这个设计。
代码验证示例
你提供的LINQPad代码能直观体现这个设计的作用:
var jsonDoc = System.Text.Json.JsonDocument.Parse("[\"a\",\"b\",\"c\"]"); System.Text.Json.JsonElement.ArrayEnumerator arrEnum = jsonDoc.RootElement.EnumerateArray(); System.Text.Json.JsonElement.ArrayEnumerator arrEnum1 = arrEnum.GetEnumerator(); // 第一次遍历,直接使用arrEnum的枚举逻辑 foreach (var el in arrEnum){ el.Dump("0"); } // 第二次遍历,调用GetEnumerator()生成新枚举器,重新从头遍历 foreach(var el in arrEnum1){ el.Dump("1"); }
内容的提问来源于stack exchange,提问作者GrumpyRodriguez
相关产品推荐
相关产品推荐

