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
,所以這是實現這種優化的潛在突破變化。