根据我在阅读D时的理解,在变量上使用immutable
关键字时,必须在编译时知道变量的值,而C#的readonly
不必是已知的,并且readonly
字段可以在类构造函数中使用non -静态值。 D有可能吗?
最佳答案
由于似乎对不可变存在一些混淆(从原始问题和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();
所以我们要构造类型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
的情况下调用方法。对于题外杂乱,我深表歉意,但我发现很多人对此主题感到困惑。
关于c# - 等价于D中的C# `readonly`关键字?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/6036807/