为D中的const和非const结构提供@property

Par*_*bay 2 d const properties

我用这种方式定义一个简单的结构:

struct Person{
    private string _name;

    @property ref string name() { return _name; }
}
Run Code Online (Sandbox Code Playgroud)

@property注释是真的很酷,但我不知道我应该如何使用它正确.

以上是相当不错的,但我无法传递Person给需要in Person例如的函数:

void fun(in Person p) { ... } 
Run Code Online (Sandbox Code Playgroud)

为避免复制,Person我必须声明参数ref,但我不修改它.

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


编辑:要跟进,可以同样适用于循环吗?

void fun(in Person[] people) {
    foreach(Person p; people) { ... }
}
Run Code Online (Sandbox Code Playgroud)

现在我不想复制人,但我不能使用,ref Person因为它是常量.所以我必须ref const(Person) p在循环中写入成为loong.

Jon*_*vis 5

通常,你会做什么

@property string name() const { return _name; }
@property void name(string value) { _name = value; }
Run Code Online (Sandbox Code Playgroud)

你不会打扰ref(当然,对于一个string,没有太多意义).对于您希望避免复制的更复杂类型,您可以返回const ref,例如

@property ref const(Foo) foo() const { return _foo; }
@property void foo(Foo value) { _foo = value; }
Run Code Online (Sandbox Code Playgroud)

可以重置setter以使其ref Foo除了之外被接受Foo,但没有太多意义,因为您将复制传入Foo以将其分配给它_foo.

如果你真的想要,你可以ref从吸气器返回并重载它,例如

@property ref const(Foo) foo() const { return _foo; }
@property ref Foo foo() { _foo; }
Run Code Online (Sandbox Code Playgroud)

在这种情况下,非const重载可以用作setter,但是如果你要这样做,为什么还要使用属性呢?此时,您可能只需将成员变量设为public,因为该属性根本不保护它.通过返回非const ref,你已经失去了对成员变量设置方式的控制,并且已经有效地将其作为公共成员变量公开,除了你有额外的功能管道.它给你的唯一好处是你可以在返回之前做一些事情,并且在调用属性时将调用类型的不变量(如果有的话)(而不会使用公共成员变量),但因为变量可以在没有你控制的情况下设置,与简单地将成员变量公开的简单性相比,这些好处具有可疑的价值.

所以,一般来说,第一个例子是要走的路,偶尔,第二个例子是更好的,但是与第三个例子相比,这可能是毫无意义的.

编辑:

正如Kozzi11指出的那样,你可以实现第三个例子

@property auto ref foo() inout { return _foo; }
Run Code Online (Sandbox Code Playgroud)

要么

@property ref inout(Foo) foo() inout { return _foo; }
Run Code Online (Sandbox Code Playgroud)

而不是有两个函数,但我对它的观点并不比公共成员变量更好.

编辑2:关于你对问题的编辑...

如果你想避免在循环中复制,你必须明确表示类型.

foreach(p; people) { ... }
Run Code Online (Sandbox Code Playgroud)

会工作,但它会Person在迭代时复制每个人people,而

foreach(ref Person p; people) { ...}
Run Code Online (Sandbox Code Playgroud)

要么

foreach(ref const(Person) p; people) { ...}
Run Code Online (Sandbox Code Playgroud)

将避免复制每个Person.