2016-01-13 120 views

回答

5

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 1ldloca.s加載結構的地址進行比較。

附註:後來的F#版本確實做了C#不能做的優化。因爲它是F#中的一種常見模式,可以遍歷不可變數據結構的F#列表,所以使用枚舉數進行迭代是無效的。所以F#有一個列表的特例,並且在這種情況下應用更高效的算法。在C#中迭代F#列表將回退到枚舉器。

也可以實現IList類型的特殊處理,但由於可能有人以「有趣」的方式實現了IList,所以這是實現這種優化的潛在突破變化。