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

V.B*_*.B. 4 .net f#

这是一个详细的答案,关于C#编译器foreachIEnumerator<T>可变结构的情况下如何优化.

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

Jus*_*mer 5

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 1ldloca.s加载结构的地址.

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

也可以对IList类型实现特殊处理,但由于有可能某人IList以"有趣"的方式实现,因此实现这种优化是一个潜在的重大变化.