質問
このは明らかにそうではありませんは、ベストプラクティスではないように見えます。なぜそれがベストプラクティスではないのか、またはこれがどのように機能するのかを誰かが説明できますか?説明を提供する本や記事をいただければ幸いです。
//The constructor
public Page_Index() {
//create a local value
string currentValue = "This is the FIRST value";
//use the local variable in a delegate that fires later
this.Load += delegate(object sender, EventArgs e) {
Response.Write(currentValue);
};
//change it again
currentValue = "This is the MODIFIED value";
}
出力される値は、2番目の値" Modified" です。コンパイラの魔法のどの部分がこの作業を行っていますか?これは、ヒープ上の値を追跡し、後で再度取得するのと同じくらい簡単ですか?
[編集]:コメントをいくつか指定し、元の文をいくつか変更します...
解決
currentValueはローカル変数ではなくなりました。キャプチャされた変数です。これは次のようにコンパイルされます:
class Foo {
public string currentValue; // yes, it is a field
public void SomeMethod(object sender, EventArgs e) {
Response.Write(currentValue);
}
}
...
public Page_Index() {
Foo foo = new Foo();
foo.currentValue = "This is the FIRST value";
this.Load += foo.SomeMethod;
foo.currentValue = "This is the MODIFIED value";
}
Jon Skeetは C#の詳細でこれを非常によく書いており、詳細ではありません)ディスカッションこちら。
変数currentValueはスタックではなくヒープ上にあることに注意してください。これには多くの意味があります。特に、さまざまな呼び出し元が使用できるようになっています。
これはjavaとは異なります。javaでは、変数の値がキャプチャされます。 C#では、変数自体がキャプチャされます。
他のヒント
より多くの質問は、ローカル変数をどのように使用するかということです [MG edit:" Ack-これを無視...... ";後に追加されました]
それがポイントです。それは本当にローカル変数ではありません -少なくとも、(スタックなどで)通常それらをどのように考えるかという点ではそうではありません。一見似ていますが、そうではありません。
また、情報については、「グッドプラクティスではありません」を参照してください。 -匿名メソッドとキャプチャされた変数は、実際には非常に強力なツールです。イベントを操作する場合は特に 。自由に使用してください。ただし、このルートを下る場合は、実際に何が起こっているのかを確認するために、ジョンの本を取り上げることをお勧めします。
クロージャー/デリゲート内の変数の値をキャプチャする必要があります。そうでない場合は、見たように変更できます。
currentValueをデリゲートのローカル変数(内部)に割り当てます。