|  |  | 
 
| 連載:[完全版]究極のC#プログラミングChapter3 新しい繰り返しのスタイル ― yield return文とForEachメソッド川俣 晶2009/08/31
 |  | 
| 
 | 
3.12 性能比較
 さて、ここで気になるのは反復子とForEachメソッドのどちらを使うべきかである。ソースコードの簡潔さは大差ないとすれば、残ったポイントは性能といえる。
 そこで、反復子とForEachメソッドの速度比較を行ってみた。リスト3.14はそのために作成したテストプログラムである。
| 
 
| using System;using System.Collections.Generic;
 
 class Program
 {
 private static IEnumerable<int> getCounter(int from, int to)
 {
 for (int i = from; i <= to; i++) yield return i;
 }
 
 private static void forEach(int from, int to, Action<int> action)
 {
 for (int i = from; i <= to; i++) action(i);
 }
 
 static void Main(string[] args)
 {
 const int TestCount = 1000000000;
 DateTime start1 = DateTime.Now;
 int sum1 = 0;
 
 foreach (int i in getCounter(1, TestCount))
 {
 sum1 += i;
 }
 Console.WriteLine(DateTime.Now - start1);
 
 DateTime start2 = DateTime.Now;
 int sum2 = 0;
 
 forEach(1, TestCount, delegate(int i)
 {
 sum2 += i;
 });
 
 Console.WriteLine(DateTime.Now - start2);
 Console.WriteLine(sum1 == sum2);
 }
 }
 
 |  | 
| リスト3.14 反復子とForEachメソッドの速度比較 | 
| 
 
| 00:00:20.588058600:00:07.5447544
 True
 
 |  | 
| リスト3.14の実行結果(Visual Studio 2008のリリースビルド) | 
 実行結果は、1行目が反復子による実行時間、2行目はForEachメソッドによる実行時間、3行目は2つの処理結果の累積値が同じ(つまり、同じ回数を繰り返した証拠)ということを示すTrueが出力されている。
 これを見ると一目瞭然だが、ForEachメソッドを使ったほうが圧倒的に速い。デバッグビルドにすると差は縮まるが、やはりForEachメソッドのほうが速い。
 なぜForEachメソッドのほうが速いのかは、内部構造を考えれば容易にわかるだろう。ForEachメソッドは、繰り返し1回ごとにメソッドを1回だけ呼ぶ。しかし、反復子はMoveNextメソッドを呼んでからCurrentプロパティで値を取得する必要があり、2回の呼び出しが発生する。さらに、周辺にかなり込み入ったコードが生成されていることから考えて、大きな性能差が出るのはやむをえないところだろう。
 さて、ここでの結論は列挙よりもForEachメソッドを使うほうが優れている……ということでよいのだろうか?  自作のオブジェクトに列挙インターフェースを付けることは意味がなく、ForEachメソッドさえ付けておけばよいのだろうか?
 そうではない。実は、C# 3.0のキーとなる重要技術の1つであるLINQ(第15章〜第18章参照)は「列挙できるものはクエリできる」という機能を発揮する。単に高速に列挙するだけならForEachメソッドでもよいのだが、LINQのクエリ式の中でオブジェクトを活用したいと思うなら、列挙インターフェースを追加することは重要な意味を持つ。そして、それをyield return文で簡潔に記述するノウハウにも重要な意味がある。
【Exercise】練習問題
 foreach文とForEachメソッドについて誤った説明を選べ。
- 1 実行速度に差がある
-   foreachは文であるがForEachはメソッドなので、使いたい対象を列挙するForEachメソッドを作成しないと使えない
-   foreach文そのものは言語の一部なので自作することは難しいが、ForEachメソッドは簡単に自作できる
-  yield return文で列挙できる
-  名前が違う
 ◎解答:「 4 」(この行をマウスで選択してください)
 
 
 
	
		Insider.NET 記事ランキング
		
		
			本日
			月間