0

可能重复:
C# - Eric Lippert 的博客中的 foreach 标识符和闭包
:“不要关闭循环变量”</a>

我使用 lambda 表达式作为ThreadStart参数,使用Thread类在新线程中运行方法。这是我的代码:

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

您应该从中创建一个不同的变量,从而不更改原始值。

毕竟,你真正要做的只是调用同一个旧的“函数”,lambda 表达式一遍又一遍地传递变量 i,这确实发生了变化。就像您将 var i 的初始值存储在某处一样。

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

这一行只是创建一个新函数并将其分配给一个变量。除其他外,此函数将值传递nDo函数。但它不是调用该Do函数,它只是创建一个函数,该函数在执行时将调用该Do函数。

然后,您启动一​​个调用函数等的新线程,但您的新线程仍在执行Do(n),将n变量传递给Do. 该部分不会改变 - 您创建了一个函数,该函数引用内存中的特定位置(由变量表示n)并继续引用内存中的该位置,即使您更改了存储在那里的值。

我相信以下内容会“修复”您的代码:

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

这会将 的值传递n给由 表示的函数loop,但该loop函数会在内存中创建一个新位置(由 表示x)来存储该值。内存中的这个新位置不受后续更改的影响n。也就是说,你创建的函数并没有直接引用内存中n指针指向的地方。

于 2012-10-28T03:49:17.873 回答