Equivalent to the C # `readonly` keyword in D?

From what I understand when reading in D, when using the immutable keyword for a variable, the value of the variable must be known at compile time, while C # readonly not necessary, and readonly fields can be assigned in the class constructor using non-static values. Is this possible in D?

+7
source share
4 answers

There seems to be some confusion (both from the original question and due to the large commentary) regarding immutability, I thought I'd add aside.

When you say immutable int i = 42 , you say that I will not be changed, and not that this value is known at compile time. immutable is actually a type modifier and creates a new type. immutable T is a short hand for immutable(T) . immutable(T) creates a T that can never be changed, that is, if you read the value and then call the function, the value will be the same. Compare this to const(T) , which provides a weaker guarantee that this type instance will not be changed, but someone may have changed access to it somewhere else, so if you read the value and then call the function, you donโ€™t can accept the value will be the same.

In general, immutable(T) != T However, there are certain situations when they are implicitly converted into each other. If T is a type that is said to have no "volatile indirection", for example. That is, if I pass the function a immutable(int) , they will receive a copy - there is no way that this function can change the value passed by me, because it is copied - if the type system did not allow this, it would just be annoying without any additional guarantees , therefore, the D-type system allows this. However, if I pass in immutable (int *), which can be changed by the calling function. In the case of structures, if any member has a variable indirectness, then, as they say, it also has.

So, in order to turn away from theory and return to more practical issues, it is not entirely true that immutable values โ€‹โ€‹must be known at compile time and that there is no good way to create them. However, a single mutation can occur inside the constructor. For simple scalar types, this is pretty obvious:

 immutable(int) i = rand(); 

But what about something like an object? Well, to build type T we use

 auto t = new T(); 

therefore, to construct the type of immutable (T), we use

 auto t = new immutable(T)(); 

here is a more complete small example

 class Useless { int i; this(int i) { this.i = i; } } int main(string[] args) { auto o = new immutable(Useless)(cast(int) args.length); //oi = 17; error return oi; // fine } 

As you can see, mutation can occur inside the constructor. You can read member variables, but you cannot write them (immutability is transitive, that is, each member (and each member of the members) becomes immutable if the parent does. You can call methods only if they are marked as const .

I apologize for the impassivity, but I see that many people seem to be confused on this issue.

+6
source

In D2, the const member can only be initialized inside the constructor (or directly in the class declaration, but not in both):

 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 } 
+10
source

The answer to fwend is mostly dead, but if you are looking for something a little less verbose, you can always do mixin to automate it. Unconfirmed code below to give a general idea:

 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"; } 

Using:

 class Foo { mixin(readOnly("int", "num")); void incNum() { _num++; } } 
+3
source

I declare the field private and then access it to access it

+2
source

All Articles