[cs] /language 又はビルドペインの詳細設定中にある言語バージョンに関して注意すべきforeachの挙動

このエントリは、2012/08/31現在に、実際に動かした結果に関する考察で有り、それ以上の検証は行ってないのでその点ご了承の程を。

どー言うことなのか

VS2010迄は*1、λ内でforeachの要素をキャプチャする際、以下のようなサンプルを書いた場合、直感的では無い結果になってました。

using System;
using System.Collections.Generic;

namespace ConsoleApplication1
{
	class Program
	{
		static void Main(string[] args)
		{
			IEnumerable<int> ite = new int[] {0, 1, 2, 3, 4};

			Action action = null;

			foreach (var i in ite)
			{
				action += () => Console.WriteLine(i);
			}

			action();
			Console.ReadLine();
		}
	}
}

このアウトプットは

4
4
4
4
4

しかしVS2012で上記コードを実行すると

0
1
2
3
4

となり、大方の場合、意図通りになります。

で、この辺の詳細に関しては今回割愛させていただきます。興味を持たれた方は、C#言語仕様 Version5.0のP279に記載があるのでご覧頂ければと思います。

何を注意すべきなのか

コマンドラインC#コンパイラを叩いた場合/languageオプションで又はVS上ではプロパティにある、ビルドペイン最下の詳細設定で言語バージョンを指定出来ます。この場合、個人的には、出力結果も従前と同じように4の羅列になると考えていたのですがさに非ず、結果は変更後のC#5.0と同じ結果になりました。*2
MSDNでこの辺に関するコトをつらつらと探していたんですが、わかったことは/languageの解説にせよ、詳細設定の言語バージョンの解説にせよコンパイラが受容する構文規則が変化するとだけ書いてあり、従前のコンパイラと同様の出力結果を返すとの記載は見当たりませんでした。

従って、従前と同様の挙動をさせたいと言う意図で、言語バージョン又は/languageを変更しても望む結果を得ることは出来ないので注意すべきかなと。*3

*1:何故C#4.0と言わないかは後述。

*2:そしてこれが、C#4.0と先に言えなかった理由です。

*3:個人的に従前の結果は理由は理解してましたが、非直感的で有り今回の結果は直感的なので何ら問題になるとは思ってませんが。。。