半検証する簡単なテスト。私はただ見るために小さなテストをしました。これがコードです:
static void Main(string[] args)
{
List<int> intList = new List<int>();
for (int i = 0; i < 10000000; i++)
{
intList.Add(i);
}
DateTime timeStarted = DateTime.Now;
for (int i = 0; i < intList.Count; i++)
{
int foo = intList[i] * 2;
if (foo % 2 == 0)
{
}
}
TimeSpan finished = DateTime.Now - timeStarted;
Console.WriteLine(finished.TotalMilliseconds.ToString());
Console.Read();
}
そして、これがforeachセクションです:
foreach (int i in intList)
{
int foo = i * 2;
if (foo % 2 == 0)
{
}
}
forをforeachに置き換えたところ、foreachは20ミリ秒速くなりました- 一貫して。foreachは113-119msでしたが、forは135-139msでした。私は何度か入れ替えて、起動したばかりのプロセスではないことを確認しました。
ただし、fooとifステートメントを削除すると、forは30 ms速くなりました(foreachは88ms、forは59ms)。どちらも空の殻でした。foreachが変数をインクリメントしているのと同じように、foreachが実際に変数を渡したと想定しています。追加した場合
int foo = intList[i];
その後、約30ms遅くなります。これは、fooを作成して配列内の変数を取得し、それをfooに割り当てることと関係があると想定しています。intList [i]にアクセスするだけの場合、そのペナルティはありません。
正直なところ、すべての状況でforeachが少し遅くなることを期待していましたが、ほとんどのアプリケーションでは問題になるほどではありませんでした。
編集:Jonsの提案を使用した新しいコードは次のとおりです(System.OutOfMemory例外がスローされる前に、134217728が最大のintになります):
static void Main(string[] args)
{
List<int> intList = new List<int>();
Console.WriteLine("Generating data.");
for (int i = 0; i < 134217728 ; i++)
{
intList.Add(i);
}
Console.Write("Calculating for loop:\t\t");
Stopwatch time = new Stopwatch();
time.Start();
for (int i = 0; i < intList.Count; i++)
{
int foo = intList[i] * 2;
if (foo % 2 == 0)
{
}
}
time.Stop();
Console.WriteLine(time.ElapsedMilliseconds.ToString() + "ms");
Console.Write("Calculating foreach loop:\t");
time.Reset();
time.Start();
foreach (int i in intList)
{
int foo = i * 2;
if (foo % 2 == 0)
{
}
}
time.Stop();
Console.WriteLine(time.ElapsedMilliseconds.ToString() + "ms");
Console.Read();
}
そしてここに結果があります:
データを生成しています。forループの計算:2458ms foreachループの計算:2005ms
それらを入れ替えて、それが物事の順序を扱っているかどうかを確認します(ほぼ)同じ結果が得られます。