如何在 D 中使对象(类)可访问?

发布于 2024-09-06 05:34:29 字数 579 浏览 5 评论 0原文

如何使一个类可在 foreach 语句中使用?

该类包含一个关联数组(例如 string[string])。因此 foreach 语句使用该数组作为源。

这就是我想要的:

auto obj = new Obj();
foreach (key, value; obj)
{
    ...
}

我需要实现类似的接口吗?

编辑:

解决方案:

public int opApply(int delegate(ref string, ref Type) dg)
{
    int result = 0;

    foreach (ref key, ref value; data)
    {
        result = dg(key, value);
        if (result != 0)
        {
            break;
        }
    }

    return result;
}

public int opApply(int delegate(ref Type) dg) 也是如此。

how can I make a class usable in a foreach statement?

The class contains a associative array (e.g. string[string]). So the foreach statement use this array as source.

So this is what I want:

auto obj = new Obj();
foreach (key, value; obj)
{
    ...
}

Do I need to implement a interface someting like that?

EDIT:

The solution:

public int opApply(int delegate(ref string, ref Type) dg)
{
    int result = 0;

    foreach (ref key, ref value; data)
    {
        result = dg(key, value);
        if (result != 0)
        {
            break;
        }
    }

    return result;
}

Same is done for public int opApply(int delegate(ref Type) dg).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

相守太难 2024-09-13 05:34:29

D1

class Foo
{
    uint array[2];

    int opApply(int delegate(ref uint) dg)
    {
        int result = 0;

        for (int i = 0; i < array.length; i++)
        {
            result = dg(array[i]);
            if (result)
                break;
        }
        return result;
    }
}

D2

结构和类对象的迭代可以通过范围来完成,这意味着必须定义[一组]属性:

D1:

class Foo
{
    uint array[2];

    int opApply(int delegate(ref uint) dg)
    {
        int result = 0;

        for (int i = 0; i < array.length; i++)
        {
            result = dg(array[i]);
            if (result)
                break;
        }
        return result;
    }
}

D2:

Iteration over struct and class objects can be done with ranges, which means [a set of] properties must be defined:

枕花眠 2024-09-13 05:34:29

OP 发布的解决方案是一个有效的解决方案,但在 D2 中还有另一个具有一组不同权衡的解决方案。 D 中的迭代可以分为内部迭代(由 opApply 处理)和外部迭代(由范围处理)。

内部迭代赋予正在迭代的对象对调用堆栈的控制。例如,这允许被迭代的对象使用递归,而无需维护显式堆栈,但使得以锁步方式迭代多个结构变得不可能。外部迭代则相反。

外部迭代是通过范围完成的。范围是定义三个方法的任何类或结构:front() 提供对范围中第一个元素的访问,popFront() 前进范围和 empty如果范围为空,() 返回true。如果范围是无限的,则可以将empty声明为常量而不是成员函数。通过这种方式,调用者可以控制调用堆栈,这是一个根据具体情况可能好也可能坏的权衡。

以下是使用范围进行迭代的示例:

/**This struct lazily produces all Fibonacci numbers.*/
struct Fibonacci {
    ulong num1 = 0;
    ulong num2 = 1;

    ulong front() {
        return num1 + num2;
    }

    void popFront() {
        auto newNum2 = num1 + num2;
        num1 = num2;
        num2 = newNum2;
    }

    // A range of Fibonacci numbers is infinite.
    enum bool empty = false; 
}

The solution posted by the OP is a valid solution, but in D2 there's another one with a different set of tradeoffs. Iteration in D can be divided into internal iteration, which is handled by opApply, and external iteration, which is handled by ranges.

Internal iteration gives the object being iterated over control of the call stack. This allows, for example, recursion to be used by the object being iterated over without maintaining an explicit stack, but makes iterating over multiple structures in lockstep impossible. External iteration does the opposite.

External iteration is accomplished via ranges. A range is any class or struct that defines three methods: front() gives access to the first element in the range, popFront() advances the range and empty() returns true if the range is empty. If the range is infinite, empty can be declared as a constant instead of a member function. In this way, the caller has control over the call stack, which is a tradeoff that can be good or bad depending on the situation.

Here's an example of using ranges for iteration:

/**This struct lazily produces all Fibonacci numbers.*/
struct Fibonacci {
    ulong num1 = 0;
    ulong num2 = 1;

    ulong front() {
        return num1 + num2;
    }

    void popFront() {
        auto newNum2 = num1 + num2;
        num1 = num2;
        num2 = newNum2;
    }

    // A range of Fibonacci numbers is infinite.
    enum bool empty = false; 
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文