C#+WPFチューニング戦記

C#とWPFで高速なコードと最適なシステムを書くためにやってきたいろいろな事を書いてみます。.NET Frameworkのソースコードを読み解きましょう。なお、ここに書かれているのは個人の見解であって何らかの団体や企業の見解を代表するものではありません。

foreachのILとループのパターン

糖衣構文としてとても有名なforeachはおおまかに2種類のILになる可能性があります。

  1. 配列に対するIL(for文とほぼ同等)
  2. IEnumerable になる IL

ループだけの速度では前者が約2倍速です。
IEnumerator が IDisposable なので IEnumerableは try - finally で囲われ、finally内でDisposeが呼ばれる・・・・ということになります。
実態の型に合わせて最適なコードを選ぶような積極的高速化は行われません。
foreachに渡す物が配列であるか、他のIEnumerableであるかだけが判断材料です。
過度な期待はできません。

さて、最適化というところに主眼を置いてC#を扱う場合、ループを組むときにはおおまかに3通りのパターンがあります。
LINQの内部実装について書いた際に扱ったことがありますが以下の3つです。

  1. 配列
  2. List<T> 長さが分かる(且つインデクサが速い)コレクション(←2014/12/6 修正)
  3. IEnumerable<T> 長さが分からないものの列挙

C#コンパイラに、型判別と最適なループに展開する属性とかを渡せたらいいのですが。
まあ、この属性を乱用したらループの都度コードが3倍になるわけで、場合によってはキャッシュヒット率の低下などかえって有害。素人にはお勧めできない仕様になってしまいますが。

あと、yield return の展開、次のバージョンではもう少しマシになってるんでしょうか。
まだ確認はしていませんが、期待と不安でいっぱいです。