什么时候将==以不同于.equals的方式覆盖? [英] When would == be overridden in a different way to .equals?

查看:55
本文介绍了什么时候将==以不同于.equals的方式覆盖?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我了解==和.equals之间的区别。这里还有许多其他问题可以详细解释差异,例如这个: .Equals和== 之间有什么区别一个:按位平等等等。



我的问题是:为什么它们都存在(我意识到必须有一个很好的理由)-它们似乎都在做相同的事情(除非被不同地覆盖)。



何时==重载的方式与.equals的重载方式不同?

解决方案


我的问题是:为什么都选择两者(我意识到必须有一个很好的理由)


如果有充分的理由,有待向我解释。 C#中的平等比较是一团糟,在我为C#设计感到遗憾的事情上,它排在第9位:



http://www.informit.com/articles/article.aspx?p=2425867



从数学上讲,平等是最简单的等价关系,它应遵循以下规则: x == x 应始终为true, x == y 应该始终与 y == x x == y x == y 和<$,则code>和 x!= y 应该总是相反的值c $ c> y == z 为真,则 x == z 必须为真。 C#的 == 等于机制可以保证这些属性 none 都不存在! (不过,值得庆幸的是, ReferenceEquals 保证了所有这些。)



正如乔恩在回答中指出的那样, == 是基于两个操作数和 .Equals(object) IEquatable 中的> .Equals(T)。为什么这些调度机制中的 都正确?平等不是支持其左手的谓词,那么为什么某些但不是全部实现都应该这样做呢?



用户定义的平等真正想要的是一种多重方法,其中两个操作数的运行时类型具有相等的权重,但这不是C#中存在的概念。



更糟糕的是,等于 == 具有不同的语义-通常一个是引用相等,另一个是值相等。天真的开发人员没有理由知道哪个是哪个,或者它们是不同的。这是漏洞的重要来源。而且,只有当您意识到GetHashCode和Equals必须达成一致,而变得更糟时,而 == 却不一定。



我是从头开始设计一种新语言的,出于某种疯狂的原因,我希望运算符重载,但我并不想这样做,所以我会设计一个能够非常简单。像这样的东西:如果在类型上实现 IComparable< T> ,那么您会自动获得< < = == != ,依此类推,运算符为您定义,并且实施它们以使其一致。即 x< = y 必须具有 x< y ||的语义。 x == y 以及!(x> y)的语义,以及 x == y 始终与 y == x 相同,依此类推。



现在,如果您的问题确实是:


我们到底是如何陷入这个令人讨厌的烂摊子?


然后我在2009年写下了一些想法:



https://blogs.msdn.microsoft.com/ericlippert/2009/04/ 09 / double-your-dispatch-double-your-fun /



TLTL是:框架设计人员和语言设计人员具有不同的目标和不同的约束,并且他们有时在设计中没有考虑这些因素,以确保整个平台上始终如一的逻辑体验。这是设计过程的失败。 >

除非有非常特殊的理由,否则我永远不会这样做。当我实现算术类型时,我总是实现所有运算符以使其彼此一致。


I understand the difference between == and .equals. There are plenty of other questions on here that explain the difference in detail e.g. this one: What is the difference between .Equals and == this one: Bitwise equality amongst many others.

My question is: why have them both (I realise there must be a very good reason) - they both appear to do the same thing (unless overridden differently).

When would == be overloaded in a different way to how .equals is overridden?

解决方案

My question is: why have them both (I realise there must be a very good reason)

If there's a good reason it has yet to be explained to me. Equality comparisons in C# are a godawful mess, and were #9 on my list of things I regret about the design of C#:

http://www.informit.com/articles/article.aspx?p=2425867

Mathematically, equality is the simplest equivalence relation and it should obey the rules: x == x should always be true, x == y should always be the same as y == x, x == y and x != y should always be opposite valued, if x == y and y == z are true then x == z must be true. C#'s == and Equals mechanisms guarantee none of these properties! (Though, thankfully, ReferenceEquals guarantees all of them.)

As Jon notes in his answer, == is dispatched based on the compile-time types of both operands, and .Equals(object) and .Equals(T) from IEquatable<T> are dispatched based on the runtime type of the left operand. Why are either of those dispatch mechanisms correct? Equality is not a predicate that favours its left hand side, so why should some but not all of the implementations do so?

Really what we want for user-defined equality is a multimethod, where the runtime types of both operands have equal weight, but that's not a concept that exists in C#.

Worse, it is incredibly common that Equals and == are given different semantics -- usually that one is reference equality and the other is value equality. There is no reason by which the naive developer would know which was which, or that they were different. This is a considerable source of bugs. And it only gets worse when you realize that GetHashCode and Equals must agree, but == need not.

Were I designing a new language from scratch, and I for some crazy reason wanted operator overloading -- which I don't -- then I would design a system that would be much, much more straightforward. Something like: if you implement IComparable<T> on a type then you automatically get <, <=, ==, !=, and so on, operators defined for you, and they are implemented so that they are consistent. That is x<=y must have the semantics of x<y || x==y and also the semantics of !(x>y), and that x == y is always the same as y == x, and so on.

Now, if your question really is:

How on earth did we get into this godawful mess?

Then I wrote down some thoughts on that back in 2009:

https://blogs.msdn.microsoft.com/ericlippert/2009/04/09/double-your-dispatch-double-your-fun/

The TLDR is: framework designers and language designers have different goals and different constraints, and they sometimes do not take those factors into account in their designs in order to ensure a consistent, logical experience across the platform. It's a failure of the design process.

When would == be overloaded in a different way to how .equals is overridden?

I would never do so unless I had a very unusual, very good reason. When I implement arithmetic types I always implement all of the operators to be consistent with each other.

这篇关于什么时候将==以不同于.equals的方式覆盖?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆