【问题标题】:If DateTime is immutable, why does the following work?如果 DateTime 是不可变的,为什么以下工作?
【发布时间】:2011-02-19 17:40:52
【问题描述】:

我以为我理解了 Immutable 的含义,但是我不明白为什么以下编译和工作:

DateTime dt = DateTime.Now;

Console.WriteLine(dt);

将下一部分复制粘贴几次

dt = DateTime.Now;
Console.WriteLine(dt);
Console.ReadLine();

正如预期的那样,它运行了,当我按下回车键时,它会显示下一次......我认为这是不可能的,我需要创建一个新对象。为什么允许/工作?或者,我正在使用的书是错误的,并且 DateTime 不是一成不变的(但是我已经在多个来源上阅读过这个)?

【问题讨论】:

    标签: c# .net datetime


    【解决方案1】:

    您只是告诉变量dt 引用DateTime 的另一个实例。在后台,DateTime.Now 属性在您每次访问时都会生成一个新的 DateTime 实例。

    【讨论】:

    • ahhh - 所以我误解了意思......我的对象是可变的,.now/时间/日期的来源不是(我想我明白,我无法解释。 ..)
    • @Wil:您可以更改变量,但不能更改变量指向的内容。打个比方,你可以在某物上贴一个标签,把标签拿出来再贴在别的东西上,但你并不能改变贴上标签的东西,只改变标签所在的位置。
    【解决方案2】:

    DateTime 对象本身是不可变的,但不是引用 dtdt 可以更改它指向的DateTime 对象。不变性是指我们不能更改 DateTime 对象中的变量。

    例如,我们不能去

    dt.Day = 3;
    

    dt 本身只是一个指向DateTime 对象的引用变量。根据其定义,它可以变化

    正如pst 提到的那样,readonlyconst 可能更接近您的想法,您无法更改变量的值。


    旁注:DateTimeStructure,因此是 value type,我将 dt 称为“参考”是一种误导。但是,我认为dt 仍然只是一个“指向”不可变对象的变量,并且变量本身仍然是可变的,这仍然是正确的。感谢dan04 指出这一点。

    【讨论】:

    • 也许提到readonlyconst(尽管这些修饰符仅适用于成员)。
    • 非常有道理 - 你和 BoltClock 都有很好的答案,所以在 8 分钟内,我会掷硬币!
    • 这与速度无关!!!而你的首先详细介绍了(两者都赞成)-我只是希望我能接受两者,所以硬币是最公平的!
    • DateTime 不是struct 而不是class
    • @ZachL,底部的澄清很有帮助,但最好改写你的答案,这样它就不需要澄清,也许沿着“,但不是variable dt" 中存储了什么对象
    【解决方案3】:

    Now 属性类似于:

     DateTime Now {
         get {
             // Get the OS time
             return new DateTime(year, month, day, hour, min, sec...)
         }
     }
    

    (技术上是错误的,Now 在内部调用调用操作系统的 UtcNow :-),但你明白了)。

    DateTime.Now 是 DateTime 的工厂 :-)

    【讨论】:

      【解决方案4】:

      this

      阅读所有这些方法的描述。它总是说“返回一个新的日期时间......”。它不会改变当前的 DateTime 对象,因此它是不可变的。

      变量引用是另一回事。可以将其视为指向实际不可变 DateTime 对象的指针,该对象可以更改为指向不同的对象。

      【讨论】:

        【解决方案5】:

        如果非平凡结构类型的实例存储在可写存储位置(非readonly 字段、局部变量、数组槽等),则其所有字段都是可变的。如果实例存储在不可写的存储位置(readonly 字段、编译器生成的临时值等),则其所有字段都不会是可变的。 “不可变结构类型”的概念是用词不当,因为声明:

        myStruct1 = myStruct2; // Assume variables are of the same structure type
        

        如果myStruct1是可写的,将myStruct1的所有公共和私有字段替换为myStruct2的对应字段;如果myStruct1 不可写,则该语句将生成编译时错误。 结构的代码在这件事上没有发言权,甚至不会被通知分配已经发生

        尽管DateTime 没有提供可以修改现有DateTime 实例的方法除了通过整体结构赋值,它无法阻止代码覆盖一个实例的字段另一个的内容,就像 dateTimeVariable = DateTime.Now; 一样。

        【讨论】:

          【解决方案6】:

          答案很简单。 DateTime 不是一成不变的。它是一个结构。而且我不知道怎么可能有一个不可变的结构。

          如果你这样做:

          DateTime d1 = DateTime.Now;
          DateTime d2 = DateTime.Now;
          d1 = d2;
          

          然后,结构 d1 将被 d2 的值覆盖。

          (DateTime 实际上只有一个值。如果您运行反编译器,我相信它是一个名为“ticks”的私有字段。)

          没有参考资料,或任何其他时髦的东西。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-07-04
            • 2019-01-09
            • 1970-01-01
            • 1970-01-01
            • 2020-05-31
            • 2010-10-16
            相关资源
            最近更新 更多