0

重複
の可能性: C# - foreach 識別子とクロージャー
Eric Lippert のブログより: 「ループ変数を閉じないでください」</a>

ThreadStartThreadクラスを使用して新しいスレッドでメソッドを実行するために、パラメーターとしてラムダ式を使用しています。これは私のコードです:

delegate void del();

static void Do(int i)
{
    Console.WriteLine(i);
}

static del CreateLoop(del Do)
{
    return () =>
    {
        while (true)
        {
            Do();
            Thread.Sleep(500);
        }
    };
}

static void Main(string[] args)
{
    int n = 0;
    var loop = CreateLoop(() => Do(n));
    new Thread(() => loop()).Start();
    Thread.Sleep(500);
    n = 1;
}

そして、これは出力です:

0
1
1
1
...

それはどのように可能ですか?
整数変数 の値を変更すると、 (のパラメータ) のn値も変更されるのはなぜですか?iDo

4

2 に答える 2

0

元の値を変更しないように、それから別の変数を作成する必要があります。

結局のところ、実際に行っているのは、変数 i を何度も何度も渡すラムダ式である、同じ古い「関数」を呼び出すことだけであり、これは実際に変化します。var i の初期値をどこかに保存しているようには見えません。

于 2012-10-27T23:34:25.990 に答える
0
var loop = CreateLoop(() => Do(n));

この行は、新しい関数を作成して変数に代入しているだけです。この関数は、特に値nDo関数に渡します。しかし、それは関数を呼び出すのではなくDo、実行時に関数を呼び出す関数を作成するだけDoです。

次に、関数などを呼び出す新しいスレッドを開始しますが、新しいスレッドはまだ実行中であり、変数をDo(n)に渡します。その部分は変わりません - メモリ内の特定の場所 (変数 で表される) を参照する関数を作成し、そこに格納されている値を変更してもメモリ内のその場所を参照し続けます。nDon

以下がコードを「修正」すると思います:

var loop = (int x) => () => CreateLoop(() => Do(x));
new Thread(loop(n)).Start();

これnにより、 で表される関数にの値が渡されますloopが、loop関数は、値を格納するメモリ ( で表されるx) 内に新しい場所を作成します。メモリ内のこの新しい場所は、その後の への変更の影響を受けませんn。つまり、作成した関数nは、ポインターがあるメモリ内の場所を直接参照しません。

于 2012-10-28T03:49:17.873 に答える