C#:为什么没有自动生成的equals / gethashcode / == /!=?

时间:2015-04-13 22:24:10

标签: c#

我想知道是否有特定原因因为C#没有自动生成EqualsGetHashCodeoperator ==operator !=适用于参考类型中的价值比较。

*说明: 我没有看到一种简单的方法来快速请求"比较实际对象"操作参考类型的值/内容。来自C ++背景我觉得它应该由编译器在用户的简单请求下自动完成。 缺乏这一特征很可能表明它可能违背了语言的设计目标" /"愿景" /"哲学"。所以我想知道这个功能被认为是不重要的原因。

- 原始文字 -

据我所知,Equals相当于很少与null,尝试演员和逐场比较的比较。

GetHashCode几乎相当于使用某些操作的成员的所有哈希的组合(乘以overflow,xor,任何东西)。

据我所知,它应该是自动化的:默认情况下应该生成方法,或者应该有一种简单的方法来请求默认实现。但是,没有这样的事情。为什么呢?

据我了解,这要么是持续多年的大规模技术监督,要么是某种我不知道的语言哲学。

那么,原因是什么?

2 个答案:

答案 0 :(得分:3)

对于值类型,自动为您实现Equals和GetHashCode <(虽然实现使用反射,因此编写自己的代码更快)。

对于参考类型,您不清楚是要比较内容还是比较引用。我用过这两个。如果我正在写一个不可变类型,我可能希望它Equals来比较它的内容。对于其他任何事情,我可能希望默认的Equals实现仅在我将实例与自身进行比较时返回true(引用相等);在这种情况下,比较内容是错误的。

因此,对于值类型(由其内容定义),.NET会为您提供所需的内容(但不如您自己编写的那样高效)。对于参考类型,您必须选择内容相等,因为这通常不是您想要的。

答案 1 :(得分:3)

为了使编译器/框架有效地自动生成与等价相关的方法,它需要能够区分两种等价和多种引用。例如,假设Foo具有类型int[]的单个字段,并且Foo的两个实例保持对包含序列{1,2,3}的不同数组的引用。这些实例的引用之间的比较是否应该报告它们相等将取决于Foo保存数组引用的目的以及请求代码保持对Foo个对象的引用的目的比较。

如果数组的内容都不会被更改,那么两个Foo实例应该相互报告为永久等效(并且目前也是等效的);如果可以修改数组,但只有在保持对Foo实例的引用的代码请求时,那么实例应该报告自己当前是等效的,但不是永久等效的[如果代码只包含对{ Foo实例并且从不共享它或调用它的任何变异方法,然后它可以知道该实例的状态永远不会改变,即使该实例不知道]。如果对数组的引用掌握在可能修改它们的外部代码的手中,那么即使数组目前保持相同的值,实例也不相等。

由于类型系统无法知道在int[]字段上进行何种比较,因此无法生成语义上有意义的相等覆盖。