F#编译器是否像C#编译器一样支持foreach优化

时间:2016-01-13 19:39:11

标签: .net f#

This is a detailed answer关于foreach是一个可变结构的情况下C#编译器如何优化IEnumerator<T>

F#编译器是否执行相同的优化?

1 个答案:

答案 0 :(得分:5)

AFAICT似乎F#以与C#类似的方式对待valuetype枚举器:

以下是来自简单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()

此代码还使用valuetype声明local 1ldloca.s来加载结构的地址。

作为旁注:后来F#版本确实进行了C#不做的优化。因为F#中的常见模式是迭代不可变数据结构的F#列表,所以使用枚举器进行迭代是无效的。所以F#有一个列表的特殊情况,在这种情况下应用更有效的算法。在C#中迭代F#列表将回退到枚举器。

也可以为IList类型实现特殊处理,但由于有可能某人以“有趣”的方式实现IList,因此实施此类优化可能会发生重大变化。