4
This is a detailed answer关于在IEnumerator<T>
是可变结构的情况下,C#编译器如何优化foreach
。F#编译器是否支持与C#编译器相同的foreach优化
F#编译器是否执行相同的优化?
This is a detailed answer关于在IEnumerator<T>
是可变结构的情况下,C#编译器如何优化foreach
。F#编译器是否支持与C#编译器相同的foreach优化
F#编译器是否执行相同的优化?
AFAICT似乎F#对待VALUETYPE以类似的方式枚举为C#:
下面是一个简单的C#程序的IL代码的分解段,它使用的foreach一个多IEnumerable<T>
.locals init (
[0] valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<int32>,
[1] int32 v
)
IL_0025: ldloca.s 0
IL_0027: call instance bool valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<int32>::MoveNext()
注意local 0
是一个值类型,它使用ldloca.s
加载结构的地址。
与F#
.locals init (
[0] class [mscorlib]System.Collections.Generic.List`1<int32> ra,
[1] valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<int32>
)
IL_000e: ldloca.s 1
IL_0010: call instance bool valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<int32>::MoveNext()
此代码还使用值类型声明local 1
和ldloca.s
加载结构的地址进行比较。
附注:后来的F#版本确实做了C#不能做的优化。因为它是F#中的一种常见模式,可以遍历不可变数据结构的F#列表,所以使用枚举数进行迭代是无效的。所以F#有一个列表的特例,并且在这种情况下应用更高效的算法。在C#中迭代F#列表将回退到枚举器。
也可以实现IList
类型的特殊处理,但由于可能有人以“有趣”的方式实现了IList
,所以这是实现这种优化的潜在突破变化。