4

次のコードでエラーが発生する理由を理解するのに少し苦労しています。

 var funs = Enumerable.Range(0, 10).Select(x => (int y) => x + y);
 foreach (var fun in funs)
   Console.WriteLine("{0}", fun(10));

エラーは、「暗黙的に型指定されたローカル変数宣言は、'System.Collections.Generic.IEnumerator.Current' で初期化できません」です。私はそれを修正する方法を知っています(選択するタイプを指定するか、 などSelect<int, Func<int, int>>のヘルパーメソッドprivate static Func<T1, TR> MakeFunc<T1, TR>(Func<T1, TR> f) { return f; }を使用してSelect(x => MakeFunc(y => x + y)).

ただし、コンパイラが型を推測できない理由を理解したいと思います。これまでのところ、7.15.6 によると、内側のラムダを Func または Expr に変換する必要があるかどうかを判断できないというのが私の最善の推測です。私は正しいですか、それとももっと何かありますか?

参考までに、7.15.6 の内容は次のとおりです。

「匿名関数 F は、直接、またはデリゲート作成式 new D(F) の実行を通じて、常にデリゲート型 D または式ツリー型 E に変換する必要があります。この変換により、匿名関数の結果が決まります。」

4

1 に答える 1

2

理由は簡単です。

コンパイルは、それがそうあるべきだとどのように結論付けることができますFunc<int, int>か? 彼は単純にできません!

独自のデリゲートがあったとします。

 public delegate int F(int i);

Func<int, int>コンパイラはとをどのように選択できますFか? これらはまったく異なる型ですが、2 つの共通点があります。両方のデリゲートがあり、同じシグネチャ (1 つのパラメーターと戻り値の型、両方とも type int) を持ちます。

したがって、コンパイラは選択できません。あなたはそれをしなければならないでしょう:

var funs = Enumerable.Range(0, 10).Select<int, Func<int,int>>(x => y => x + y);

また

var funs = Enumerable.Range(0, 10).Select<int, F>(x => y => x + y);

int1 つの小さな利点: の前にをドロップできますy

于 2013-05-19T16:49:01.233 に答える