根据我对D的了解,在变量上使用immutable
关键字时,变量的值必须在编译时已知,而C#的readonly
不需要,而readonly
字段可以在类构造函数中分配使用非静态值。这可能在D吗?D中C#`readonly`关键字的等价物吗?
回答
由于存在似乎有些混乱(来自原来的问题,并he_the_great的评论)对于不可改变的,我想我会在旁边添加一个。
当你说immutable int i = 42
,你是说我不会被修改,而不是它在编译时已知的值。 immutable
实际上是一个类型修饰符,并创建一个新类型。 immutable T
是immutable(T)
的简写。 immutable(T)
创建了一个永远不会发生变化的T,也就是说,如果您读取了该值,然后调用一个函数,则该值将是相同的。将其与const(T)
进行比较可以提供较弱的保证,即该类型的这个实例不会被修改,但是某个人可能在其他地方具有可变的访问权限,所以如果您读取该值然后调用一个函数,则不能假定该值是一样。
一般而言,immutable(T) != T
。但是,在某些情况下,它们可以隐式地相互转换。例如,如果T是一种被称为没有“可变间接”的类型。也就是说,如果我传递一个函数immutable(int)
,他们会收到一份副本 - 该函数无法修改我传递的值,因为它被复制 - 如果类型系统不允许,它会只会让人讨厌而没有额外的保证,所以D型系统可以做到这一点。但是,如果我传递一个不可变(int *),那么可以通过调用函数更改。在结构体的情况下,如果任何成员具有可变间接性,那么该结构体也被称为具有可变间接性。
因此,为了摆脱理论,回到更实际的问题,在编译时不得不知道不可变的值,并且没有好的方法来创建它们。但是,唯一的突变可能发生在构造函数内部。对于简单的标量类型,这是非常明显的:
immutable(int) i = rand();
但是对于像对象这样的东西呢?好了,来构建一个类型T,我们使用
auto t = new T();
所以构建类型不变(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
时才能调用方法。
对于这个题外话,我很抱歉,但是我看到很多人似乎对这个主题感到困惑。
谢谢您的深入解释。这清除了我在D中关于这些关键字的很多混淆(我认为我正在混合使用D 1.0和2.0语义)。 – 2011-05-18 21:25:45
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++;
}
}
在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
}
这实质上是只读行为在C#中。 – ChaosPandion 2011-05-17 22:09:32
- 1. 什么是Java中C#'var'关键字的等价物?
- 2. 什么是C#“is”关键字的VB.NET等价物?
- 3. 什么是C#“var”关键字的VB.NET等价物?
- 4. 什么是C#'is'和'as'关键字的Java等价物?
- 5. C中的boost :: bind等价物吗?
- 6. VB.NET等价于C#var关键字
- 7. 什么是Lua中的Javascript'delete'关键字等价物?
- 8. Xcode 4的Command-Shift-D等价物?
- 9. 用于Windows的D-Bus等价物
- 10. C#中fmodf的等价物?
- 11. Java中'where'fortran关键字的等价性?
- 12. BufferedImage.getRGB C#等价物?
- 13. C#4的CreateObject等价物,动态关键字和后期绑定?
- 14. C/C++中的CreateObject等价物? (COM Interop)
- 15. Encoding.Unicode.GetByteCount(str)的C++等价物?
- 16. 在Objective c中等待并通知等价物吗?
- 17. Spring Boot中的Grails'BootStrap#init等价物吗?
- 18. 在Scala中有getch()的等价物吗?
- 19. Java中的C#OnDeserialized/OnSerializaed的等价物?
- 20. android中的fgets(c langauage)的等价物
- 21. C#Java HashMap等价物
- 22. 什么是PHP的返回,中断和继续关键字的Perl等价物?
- 23. 功能块外的“返回”关键字在PHP中的折扣等价物?
- 24. C#中TreeBidiMap的等价物是什么?
- 25. 什么是C#中的vbNullChar等价物?
- 26. C#中memset的等价物是什么?
- 27. C#中bigint的等价物是什么?
- 28. C#中__DATE__,__TIME__宏的等价物#
- 29. JavaScript中有sprintf等价物吗?
- 30. Delphi中时间戳(%d)的等价物是什么?
我相信我的答案与当前版本的D不兼容。请看@Raphaël的答案。 – ChaosPandion 2011-05-17 23:13:01
不可变不需要在编译时知道,在运行期间没有任何好的方法来创建它们,没有投射 – 2011-05-17 23:24:27