根据我在阅读D时的理解,当在变量上使用immutable
关键字时,变量的值必须在编译时知道,而C#的readonly
不需要,并且可以使用非静态值在类构造函数中分配readonly
个字段。这可能在D?
答案 0 :(得分:10)
在D2中,const成员只能在构造函数内初始化(或直接在类声明中初始化,但不能同时在两者中):
import io = std.stdio;
class A
{
const int member;
this(int nb)
{
this.member = nb;
}
}
void main()
{
A a = new A(12);
io.writeln(a.member);
//a.member = 14; //Error: can only initialize const member member inside constructor
}
答案 1 :(得分:6)
由于似乎存在一些关于不可变的混淆(来自原始问题和he_the_great的评论),我想我会补充一点。
当你说immutable int i = 42
时,你说我不会被修改,而不是在编译时知道它的价值。 immutable
实际上是一个类型修饰符,并创建一个新类型。 immutable T
是immutable(T)
的简写。 immutable(T)
创建一个永远不会变异的T,也就是说,如果你读取了值,然后调用一个函数,那么值就是相同的。将此与const(T)
进行比较,它提供了较弱的保证,即该类型的实例不会被修改,但是有人可能对其他地方有可变的访问权限,所以如果你读取了值然后调用了一个函数,你就不能假设价值将是相同的。
一般来说,immutable(T) != T
。然而,在某些情况下,它们可以隐含地相互转换。例如,如果T是一种被认为没有“可变间接”的类型。也就是说,如果我传递一个函数immutable(int)
,它们会收到一个副本 - 该函数无法修改我传递的值,因为它被复制 - 如果类型系统没有允许这样,它只会令人烦恼而没有额外的保证,所以D型系统允许它。但是,如果我传递一个immutable(int *),那么可以被调用函数更改。在结构的情况下,如果任何成员具有可变间接,那么结构也被认为具有它。
因此,为了摆脱理论并回到更实际的问题,根本不可能在编译时知道不可变的值,并且没有好的方法来创建它们。但是,唯一的突变可能发生在构造函数内部。对于简单的标量类型,这很明显:
immutable(int) i = rand();
但是像物体一样呢?好吧,要构建一个类型T我们使用
auto t = new T();
所以构造我们使用的类型immutable(T)
auto t = new immutable(T)();
这是一个更完整的小例子
class Useless
{
int i;
this(int i)
{
this.i = i;
}
}
int main(string[] args)
{
auto o = new immutable(Useless)(cast(int) args.length);
//o.i = 17; error
return o.i; // fine
}
如您所见,构造函数内部可能发生变异。您可以读取成员变量,但不能编写它们(不可变是传递性的;也就是说,如果父项成员,每个成员(以及成员的每个成员)都变为不可变。只有当它们被标记为const
时才能调用方法
我为偏离话题的漫无边际道歉,但我看到很多人似乎对这个话题感到困惑。
答案 2 :(得分:3)
fwend的答案基本上是死的,但是如果你正在寻找一些不那么冗长的东西,你可以随时制作一个mixin来自动化它。下面未经测试的代码提供了一般性的想法:
string readOnly(string typeName, string varName) {
// Create a private variable that prepends an _ to the name and a
// public accessor named name.
return "private " ~ typeName ~ " _" ~ varName ~ ";\n" ~
"public " ~ typeName ~
"varName() @property { return _" ~ varName ~ ";\n";
}
用法:
class Foo {
mixin(readOnly("int", "num"));
void incNum() {
_num++;
}
}
答案 3 :(得分:2)
我将该字段声明为私有,然后使用get访问器来读取它