为D中的const和非const结构提供@property [英] Provide @property for const and non-const structures in D

查看:82
本文介绍了为D中的const和非const结构提供@property的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我以此方式定义了一个简单的结构:

I define a simple struct this way:

struct Person{
    private string _name;

    @property ref string name() { return _name; }
}

@属性注释确实很酷,但是我不知道如何正确使用它。

The @property annotation is really cool, but I don't know how should I use it properly.

上面的代码还可以,但是我不能通过人员到需要<人中的$code>的功能,例如:

The above is quite ok, but I cannot pass a Person to a function requiring in Person for instance:

void fun(in Person p) { ... } 

为避免复制我必须用 ref 声明参数,尽管我没有对其进行修改。

To avoid copying Person I have to declare the parameter with ref, though I don't modify it.

那么如何将属性语法与const-正确性结合起来?

So how to combine the property syntax with const-correctness?

编辑:
要进行跟进,是否可以将同样的方法应用于循环?

edit: To follow up, can the same apply to looping?

void fun(in Person[] people) {
    foreach(Person p; people) { ... }
}

现在我不知道'不想复制人员,但是我不能使用 ref Person ,因为它是const。因此,我必须在变成loong的循环中编写 ref const(Person)p

now I don't want to copy person, but I can't use ref Person since it's const. So I have to write ref const(Person) p in the loop which becomes loong.

推荐答案

通常,您会做的是

@property string name() const { return _name; }
@property void name(string value) { _name = value; }

,您就不必担心 ref (当然,对于字符串来说,意义不大)。对于要避免复制的更复杂的类型,可以通过 const ref 返回,例如

and you wouldn't bother with ref (certainly, for a string, there isn't much point). For more complex types that you want to avoid copying, you can return by const ref, e.g.

@property ref const(Foo) foo() const { return _foo; }
@property void foo(Foo value) { _foo = value; }

可以超载设置程序,使其接受 ref Foo Foo 一样,但是没有什么意义,因为您将复制传入的 Foo 始终将其分配给 _foo

You could overload the setter so that it accepted ref Foo in addition to Foo, but there isn't much point, since you'd be copying the passed in Foo to assign it to _foo anyway.

如果您真的想要,您可以从吸气剂中通过 ref 返回并重载它,例如

And if you really want to, you can return by ref from the getter and overload it, e.g.

@property ref const(Foo) foo() const { return _foo; }
@property ref Foo foo() { _foo; }

在这种情况下,可以将非const重载用作setter,但如果要这样做,为什么要打扰财产?那时,您最好将成员变量设为公开,因为该属性根本无法保护它。通过返回非const ref ,您将失去对成员变量设置方式的控制,并已将其有效地公开为公共成员变量,除了拥有更多的它周围的功能。它给您带来的唯一好处是您可以在返回之前做一些事情,并且在调用属性时将调用类型的不变式(如果有的话)(而不会使用public成员变量),但是因为变量可以如果在没有控制的情况下进行设置,那么与简单地简单地将成员变量设为公共状态相比,这些好处的价值值得怀疑。

in which case the non-const overload can be used as a setter, but if you're going to do that, why bother with a property? At that point, you might as well just make the member variable public, because the property isn't protecting it at all. By returning non-const ref, you've lost control over how the member variable is set and have effectively exposed it as a public member variable except that you have the extra plumbing of the function around it. The only advantages that it gives you are that you can do something before returning and that the type's invariant (if any) will be called when the property is called (whereas it won't with a public member variable), but because the variable can be set without you're control at that point, those benefits are of questionable value in comparison to the simplicity of simply making the member variable public.

因此,通常,第一个示例是行之有效的方法,偶尔,第二个示例更好,但是与第三个示例一起使用则毫无意义。

So, in general, the first example is the way to go, and once in a while, the second is better, but it's arguably pointless to go with the third example.

编辑:

Kozzi11指出可以将第三个示例实现为

As Kozzi11 points out, you can implement the 3rd example as

@property auto ref foo() inout { return _foo; }

@property ref inout(Foo) foo() inout { return _foo; }

虽然没有两个功能,但我的观点并没有比公共成员更好变量仍然适用。

instead of having two functions, but my point about it not really being much better than a public member variable still applies.

编辑2:对于您对问题的编辑...

EDIT 2: With regards to your edit to the question...

如果要避免在循环中进行复制,则必须明确指定类型。

If you want to avoid copying in the loop, you're going to have to be explicit with the type.

foreach(p; people) { ... }

可以,但是会复制每个个人遍历个人,而

will work, but it will copy each individual Person as it iterates over people, whereas

foreach(ref Person p; people) { ...}

foreach(ref const(Person) p; people) { ...}

将避免复制每个 Person

这篇关于为D中的const和非const结构提供@property的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆