AFAICT似乎F#以与C#类似的方式处理valuetype枚举器:
这是一个反汇编的IL代码片段来自一个简单的C#程序,该程序使用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()
Run Code Online (Sandbox Code Playgroud)
请注意,它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()
Run Code Online (Sandbox Code Playgroud)
此代码还使用valuetype声明local 1和ldloca.s加载结构的地址.
作为旁注:后来的F#版本确实进行了C#不做的优化.因为F#中的常见模式是迭代不可变数据结构的F#列表,所以使用枚举器进行迭代是无效的.所以F#有一个列表的特殊情况,在这种情况下应用更有效的算法.在C#中迭代F#列表将回退到枚举器.
也可以对IList类型实现特殊处理,但由于有可能某人IList以"有趣"的方式实现,因此实现这种优化是一个潜在的重大变化.