你如何让foreach为代表使用非引用类型?

时间:2014-02-24 10:04:08

标签: foreach delegates pass-by-reference d

产生问题的示例代码:

import std.stdio, core.thread;
void main() {
    ThreadGroup tg = new ThreadGroup();
    foreach (int i; 1 .. 5)
        tg.create( () => writeln(i) );
    tg.joinAll();
}

示例输出:

3
5
5
5
5

(预期输出为整数1到5。)

我不明白为什么会发生这种情况 - i不是引用类型,也没有引用它在委托中使用,所以为什么每个线程都使用{{1}的值作为调度线程时发生的任何值,而不是它给出的大概传值值?

我做了一些像这样的蹩脚尝试,但没有成功:

i

我很好奇为什么这不起作用。是不是每次都宣布一个新的foreach (int i; 1 .. 5) { scope j = i; tg.create( () => writeln(j) ); } ?为什么每个线程都引用相同的j(线程调度时其值通常为5)?

1 个答案:

答案 0 :(得分:6)

  

那么为什么每个线程都使用i的值作为调度线程时发生的任何值,而不是它给出的值传递值?

就循环体而言,它是值传递,但这不适用于在其中创建的线程。线程仍将通过其地址引用i

要解决此问题,您需要在循环内创建一个闭包:

import std.stdio, core.thread;
void main() {
    ThreadGroup tg = new ThreadGroup();
    foreach (int i; 1 .. 5)
        (i =>
            tg.create( () => writeln(i) )
        )(i);
    tg.joinAll();
}

lambda参数将存储在闭包中,为每个线程提供自己的副本。