我想知道为什么 Date 结构和对象,如 C# 的 DateTime 和 Obj-C 的 NSDate 已经成为不可变的。
我正在寻找这种设计背后的原因以及使这些信息不可变的好处,而不仅仅是“因为他们可以”
更新: 似乎有一个类似的问题,我的答案很好,但专门针对 Java,可以在这里找到:为什么我们需要不可变类?
结合我的问题的答案非常有用
我想知道为什么 Date 结构和对象,如 C# 的 DateTime 和 Obj-C 的 NSDate 已经成为不可变的。
我正在寻找这种设计背后的原因以及使这些信息不可变的好处,而不仅仅是“因为他们可以”
更新: 似乎有一个类似的问题,我的答案很好,但专门针对 Java,可以在这里找到:为什么我们需要不可变类?
结合我的问题的答案非常有用
不变性使很多事情变得更容易。如果您不必担心某些东西会在您身下发生变化,那么您不必编写很多保护代码。有很多假设是你不必做的。事情有很多可能性不会出错。
字符串、日期和其他类型的常见对象在现代语言中是不可变的,这是很常见的,因为它简化了编译器和框架,并且意味着编译器在进行优化时可以自由地做出假设。
要点是,以很小的价格(如果您想更改值,必须创建一个新对象),您可以获得很多真正的性能、稳定性和可靠性。
我不确定 Objective C,但在 C# 中,日期由简单的数字类型支持。由于数字是不可变的,因此基于它的 Date 也是不可变的。
我不确定 Objective-C,但DateTime
's 是不可变的,因为使它们可变实际上很难正确地做到。
这是因为如果你从一个方法(包括属性)返回它们,你会得到一个副本,而不是原始的。这可能意味着以下代码不会像您预期的那样运行:
someObject.Timestamp.SetSeconds(10.0);
Where SetSeconds
is void 并改变了底层结构。
它什么也不做,因为您将获得 Timestamp 对象的副本,将其添加 10 秒,然后对该副本不执行任何操作。
绝大多数 (99.99%) 为在 .net 中使用而编写的结构(无论是在框架中还是在用户代码中定义)要么代表一个固定的独立值集合,它们可以接受对其类型合法的值的任何组合(例如a Point
,其中包含 anX
和 a Y
),或者表示单个抽象实体。Microsoft 在 .net 中的结构使用指南未能区分这些不同的使用场景,假设所有结构都符合第二种模式,不幸的是,第一种类型的结构通常以仅真正适合第二种模式的方式编写. 然而,碰巧的是,DateTime
.net 中的结构当然不能作为独立值的集合,因此指南完全适合它。
首先,没有任何好的方法DateTime
可以直接公开任何字段。结构封装没有明确的独立值集DateTime
,因此不清楚任何字段的类型应该是什么。此外,许多属性不能被合理地改变,因为它们不是独立的。例如,如果有一个DateTime
代表 2012 年 2 月 29 日的 a,并且一个将年份设置为 2011 年,然后将月份设置为 3,那么结果日期应该是什么?只对使用方法进行变异才有意义DateTime
,不幸的是,vb.net 和 C# 都将假装允许在只读结构实例上调用变异方法,方法是默默地将代码替换MyList[3].MutatingMethod();
为 horribly-brokenvar temp=MyList[3]; temp.MutatingMethod();
. 微软通过定义一个属性来解决这个问题应该是相当简单的,这样在一个只读实例上调用一个用该属性标记的方法应该会导致编译器错误而不是代码损坏,但不幸的是微软的语言人们宁愿声明可变结构是邪恶的,而不是修复语言,所以它们不会,