static void Main(string[] args)
{
var s = 3;
Func<int, Func<int>> func =
x => () =>
{
return x;
};
var result1 = func(s);
func = null;
s = 5;
var result2 = result1();
Console.WriteLine(result2);
Console.ReadKey();
}
私の理解では、xは実際には変数として宣言されていません。var x =3。代わりに、元の値を返す関数を返す外部関数に渡されます。これを返すときに、その値を記憶するためにxの周りにクロージャを作成します。その後、sを変更しても、効果はありません。
これは正しいですか?
(ちなみに出力は3ですが、期待通りです)。
編集:これがなぜだと思うのかについての図です
x = 3が関数に渡され、xを返すだけの関数が返されます。しかし、xは内部関数には存在せず、その親のみであり、nullにすると、その親は存在しなくなります。内部関数が実行されるとき、xはどこに格納されますか?親からクロージャを作成する必要があります。
さらなる解明:
int s = 0;
Func<int, Func<int>> func =
x => () =>
{
return x;
};
for (s = 0; s < 5; s++)
{
var result1 = func(s);
var result2 = result1();
Console.WriteLine(result2);
};
出力は0、1、2、3、4です
ただし、あなたの例では:
static void Main(string[] args)
{
int s = 0;
Func<int, Func<int>> func =
x => () =>
{
return s;
};
List<Func<int>> results = new List<Func<int>>();
for (s = 0; s < 5; s++)
{
results.Add(func(s));
};
foreach (var b in results)
{
Console.WriteLine(b());
}
Console.ReadKey();
}
出力は555 5 5ですが、これは必要なものではありません。変数の値は取得されておらず、元のsへの参照が保持されているだけです。
この問題を回避するために、クロージャはjavascriptで正確に作成されます。