我以为我理解了Immutable的意思,但是我不明白为什么以下编译和工作:
DateTime dt = DateTime.Now;
Console.WriteLine(dt);
复制并粘贴下一部分
dt = DateTime.Now;
Console.WriteLine(dt);
Console.ReadLine();
正如预期的那样,它会运行,当我按下回车键时,它会在下次显示...我认为这是不可能的,我需要创建一个新对象。为什么允许/工作?或者,这本书我的工作是错误的,而且DateTime不是一成不变的(但是我已经在几个来源上读到了这个)?
答案 0 :(得分:45)
DateTime
对象本身是不可变的,但不是引用dt 。允许 dt 更改它指向的DateTime
个对象。不变性指的是我们无法更改DateTime
对象内的变量。
例如,我们不能去
dt.Day = 3;
dt 本身只是一个指向DateTime
对象的引用变量。根据其定义,允许改变。
正如pst提到的那样,readonly和const可能更接近您的想法,而您无法更改变量的值。
旁注:DateTime是Structure,因此是value type,我通过调用dt
'参考'来误导我。但是,我认为dt
仍然只是一个变量'指向'一个不可变对象,而变量本身仍然是可变的。感谢dan04指出了这一点。
答案 1 :(得分:19)
您只是告诉变量dt
引用DateTime
的其他实例。每次访问时,DateTime.Now
属性都会生成一个新的DateTime
实例。
答案 2 :(得分:5)
Now属性类似于:
DateTime Now {
get {
// Get the OS time
return new DateTime(year, month, day, hour, min, sec...)
}
}
(技术上是假的,Now在内部调用调用操作系统的UtcNow :-),但你明白了。)
DateTime.Now是DateTime的工厂: - )
答案 3 :(得分:1)
请参阅this。
查看所有这些方法说明...它总是说“返回一个新的DateTime ......”。它不会更改当前的DateTime对象,因此它是不可变的。
变量引用是另一回事。可以把它看作是指向实际不可变DateTime对象的指针,可以将其更改为指向不同的对象。
答案 4 :(得分:0)
如果非平凡结构类型的实例存储在可写存储位置(非readonly
字段,局部变量,数组插槽等)中,则其所有字段都是可变的。如果实例存储在不可写的存储位置(readonly
字段,编译器生成的临时值等),则其字段都不可变。 “不可变结构类型”的概念是用词不当,因为声明:
myStruct1 = myStruct2; // Assume variables are of the same structure type
如果myStruct1
可写,将myStruct1
的所有公共和私有字段替换为myStruct2
的相应字段;如果myStruct1
不可写,则该语句将生成编译时错误。 结构的代码在此事上没有发言权,甚至不会通知发生的任务。
虽然DateTime
没有提供现有DateTime
实例可以修改的方法,除了整个结构分配,但它无法阻止代码覆盖字段一个实例与另一个实例的内容,与dateTimeVariable = DateTime.Now;
一样。
答案 5 :(得分:0)
答案很简单。 DateTime不是不可变的。这是一个结构。而且我不知道如何拥有一个不可变的结构。
如果你这样做:
DateTime d1 = DateTime.Now;
DateTime d2 = DateTime.Now;
d1 = d2;
然后,结构d1将被d2的值覆盖。
(一个DateTime真的只有一个值。如果你运行一个反编译器,它是一个名为“ticks”的私有字段我相信。)
没有任何参考资料,或其他任何时髦的东西。