foreach - 如何让 foreach 对委托(delegate)使用非引用类型?

标签 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 不是引用类型,也没有在委托(delegate)中使用它的引用,那么为什么每个线程都使用i 作为调度线程时它恰好具有的任何值,而不是它给出的可能的按值传递值?

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

foreach (int i; 1 .. 5) {
    scope j = i;
    tg.create( () => writeln(j) );
}

我也很好奇为什么这不起作用。不是每次都声明一个新的j吗?为什么每个线程都引用相同的 j(在线程调度时其值通常为 5)?

最佳答案

so why does each thread use the value of i as whatever value it happens to have when the thread is scheduled, instead of the presumably pass-by-value value it's given?

就循环体而言,它是按值传递的,但这不适用于在其中创建的线程。线程仍将通过其地址引用 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 参数将存储在闭包中,为每个线程提供自己的副本。

关于foreach - 如何让 foreach 对委托(delegate)使用非引用类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21984438/

相关文章:

excel - 用 stata 循环填充输出向量

c# - C#(或其他语言)中委托(delegate)的使用

c# - 行动 lambda 中的逆变 - C#

c++ - &table [0] [0]和&table有什么区别?

c - 为什么取消引用 C 中的引用?在 * 旁边使用 &

powershell - 无法过滤对象集合以仅选择具有最新日期的对象

PHP foreach 循环覆盖最后一条记录的所有项目

php - 在 foreach 循环中重命名 PHP 对象属性

c# - 检查 C# Action/Lambda/Delegate 是否包含任何代码/语句

c++ - 传递函数的返回值作为引用