簡體   English   中英

為什么是List <T> .ForEach比標准foreach更快?

[英]Why is List<T>.ForEach faster than standard foreach?

考慮一下:

必要的:

//The alphabet from a-z
List<char> letterRange = Enumerable.Range('a', 'z' - 'a' + 1)
.Select(i => (Char)i).ToList(); //97 - 122 + 1 = 26 letters/iterations

標准foreach:

foreach (var range in letterRange)
{
    Console.Write(range + ",");
}
Console.Write("\n");

內置的foreach:

letterRange.ForEach(range => Console.Write(range + ",")); //delegate(char range) works as well
Console.Write("\n");

我已經嘗試過將它們相互對准,並且內置的foreach速度提高了2倍,這似乎很多。

我用Google搜索了,但我似乎無法找到任何答案。

另外,關於: 在.NET中,哪個循環運行得更快,'for'或'foreach'?

for (int i = 0; i < letterRange.Count; i++)
{
    Console.Write(letterRange[i] + ",");
}
Console.Write("\n");

據我所知,不執行比標准foreach更快。

我認為你的基准是有缺陷的。 Console.Write是一個I / O綁定任務,它是您的基准測試中最耗時的部分。 這是一個微觀基准,應該非常仔細地進行,以獲得准確的結果。

這是一個基准: http//diditwith.net/PermaLink,guid,506c0888-8c5f-40e5-9d39-a09e2ebf3a55.aspx (看起來不錯,但我自己沒有驗證過)。 截至2015年8月14日,該鏈接似乎已被破壞

當您輸入foreach循環時,您將枚舉每個項目。 該枚舉導致每次迭代兩次方法調用:一次到IEnumerator<T>.MoveNext() ,另一次到IEnumerator<T>.Current 這是兩個call IL指令。

List<T>.ForEach更快,因為它每次迭代只有一個方法調用 - 無論你提供的Action<T>委托是什么。 這是一個callvirt IL指令。 這明顯快於兩個call指令。

正如其他人所指出的那樣,像Console.WriteLine()這樣的IO綁定指令會污染你的基准測試。 做一些可以完全局限於記憶的事情,比如將序列的元素添加到一起。

這是因為foreach方法沒有使用枚舉器。 枚舉器(foreach)往往比基本for循環慢:

這是ForEach方法的代碼:

public void ForEach(Action<T> action)
{
    if (action == null)
    {
        ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
    }
    for (int i = 0; i < this._size; i++)
    {
        action(this._items[i]);
    }
}

雖然我希望有所不同,但我有點驚訝它和你指出的一樣大。 使用枚舉器方法,您將創建額外的對象,然后采取額外的步驟以確保枚舉器不會失效(集合已被修改)。 您還需要通過一個額外的函數調用Current()來獲取該成員。 這一切都增加了時間。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM