I thought I understood what Immutable meant, however I don\'t understand why the following compiles and works:
DateTime dt = DateTime.Now;
Console.WriteLine
If an instance of a non-trivial structure type is stored in a writable storage location (non-readonly
field, local variable, array slot, etc.), all of its fields will be mutable. If an instance is stored in a non-writable storage location (a readonly
field, a compiler-generated temporary value, etc.), then none of its fields will be mutable. The concept of an "immutable structure type" is a misnomer, since the statement:
myStruct1 = myStruct2; // Assume variables are of the same structure type
will, if myStruct1
is writable, replace all public and private fields of myStruct1
with the corresponding fields of myStruct2
; if myStruct1
isn't writable, the statement will generate a compile-time error. The code for the structure gets no say in the matter, and won't even be notified that the assignment as taken place.
Although DateTime
provides no means by which an existing DateTime
instance can be modified except by whole-structure assignment, it can do nothing to prevent code from overwriting the fields of one instance with the contents of another, as happens with dateTimeVariable = DateTime.Now;
.
The DateTime
object itself is immutable, but not the reference dt. dt is allowed to change which DateTime
object it points to. The immutability refers to the fact we can't change the variables inside a DateTime
object.
For example, we can't go
dt.Day = 3;
dt itself is just a reference variable that points towards a DateTime
object. By its definition, it's allowed to vary.
As pst mentioned, though, readonly and const are probably closer to what you're thinking, where you can't change the value of a variable.
Side note: DateTime is a Structure, and therefore, a value type, and I'm being misleading by calling dt
a 'reference.' However, I think it still holds true that dt
is still just a variable 'pointing' at an immutable object, and the variable itself is still mutable. Thanks to dan04 for pointing that out.
See this.
Read the description of all those methods. It always says "Returns a new DateTime...". It does not change the current DateTime object, thus it is immutable.
Variable reference is a different thing. Think of it just as a pointer to the actual immutable DateTime object that can be changed to point a different one.
The Now property is something like:
DateTime Now {
get {
// Get the OS time
return new DateTime(year, month, day, hour, min, sec...)
}
}
(technically false, the Now calls internally the UtcNow that calls the OS :-), but you get the idea).
The DateTime.Now is a factory for DateTime :-)
You're simply telling the variable dt
to refer to a different instance of DateTime
. Under the hood, the DateTime.Now
property generates a new DateTime
instance every time you access it.
The answer is simple. DateTime is not immutable. It is a struct. And I don't know how it's possible to have an immutable struct.
If you do this:
DateTime d1 = DateTime.Now;
DateTime d2 = DateTime.Now;
d1 = d2;
Then, the struct d1 will be overwritten with d2's values.
(A DateTime really only has one value. If you run a decompiler it is a private field called "ticks" I believe.)
There is no reference stuff going on, or anything else funky.