== 运算符的行为是否应该与 Equals() 完全相同?
Should == operator behave exactly as Equals()?
让我们考虑 Polygon
class。大多数情况下检查相等性应该比较引用,但在很多情况下值相等性会派上用场(比如用 Assert.AreEqual
比较两个多边形时)。
我的想法是使值相等性在某种程度上次于引用相等性。在这种情况下,很明显 ==operator
应该保留其默认的引用检查实现。
那么object.Equals()
和IEquatable<Polygon>.Equals()
呢? MSDN 并不暗示 ==
和 .Equals()
应该做同样的事情,但仍然 - 它不会使 Polygon
对象的行为过于模棱两可吗?
此外,Polygon
class 是可变的。
MSDN差不多清楚了
To check for reference equality, use ReferenceEquals
. To check for
value equality, you should generally use Equals
. However, Equals as it
is implemented by Object
just performs a reference identity check. It
is therefore important, when you call Equals
, to verify whether the
type overrides it to provide value equality semantics. When you create
your own types, you should override Equals
.
By default, the operator ==
tests for reference equality by
determining if two references indicate the same object, so reference
types do not need to implement operator == in order to gain this
functionality. When a type is immutable, meaning the data contained in
the instance cannot be changed, overloading operator == to compare
value equality instead of reference equality can be useful because, as
immutable objects, they can be considered the same as long as they
have the same value. Overriding operator ==
in non-immutable types is
not recommended.
IEquatable文档也很清楚
Defines a generalized method that a value type or class implements to
create a type-specific method for determining equality of instances.
在 .NET(以及 Java)中进行相等性测试的一个主要困难是有两个有用的等价关系,每个都基于一个可以对任何 class 对象合理提出的问题,但是 .NET 对于应该由 Equals
和 GetHashCode
应该回答的问题或关系进行封装并不一致。问题是:
无论你发生什么事,你是否永远永远等同于某个特定引用所标识的对象。
你会认为自己等同于某个特定引用所标识的对象,除非或直到引用你的东西做了会影响这种等价的事情。
对于不可变对象,两种关系都应测试值是否相等。对于可变对象,第一个问题应测试引用等价性,第二个问题应测试值相等性。对于持有对可变类型对象的引用但没有人会改变的不可变对象,这两个问题都应测试该封装对象的值相等性。
我个人的建议是可变对象不覆盖 Object.Equals,但它们提供静态 属性,returns 和 IEqualityComparer
来测试值相等性。这将需要
任何不可变地封装可变对象的对象都必须
获取 IEqualityComparer
以能够报告封装对象的
值等价关系本身,但具有 IEqualityComparer
可以将这些东西存储在例如Dictionary
已提供
它们永远不会被修改。
让我们考虑 Polygon
class。大多数情况下检查相等性应该比较引用,但在很多情况下值相等性会派上用场(比如用 Assert.AreEqual
比较两个多边形时)。
我的想法是使值相等性在某种程度上次于引用相等性。在这种情况下,很明显 ==operator
应该保留其默认的引用检查实现。
那么object.Equals()
和IEquatable<Polygon>.Equals()
呢? MSDN 并不暗示 ==
和 .Equals()
应该做同样的事情,但仍然 - 它不会使 Polygon
对象的行为过于模棱两可吗?
此外,Polygon
class 是可变的。
MSDN差不多清楚了
To check for reference equality, use
ReferenceEquals
. To check for value equality, you should generally useEquals
. However, Equals as it is implemented byObject
just performs a reference identity check. It is therefore important, when you callEquals
, to verify whether the type overrides it to provide value equality semantics. When you create your own types, you should overrideEquals
.
By default, the operator
==
tests for reference equality by determining if two references indicate the same object, so reference types do not need to implement operator == in order to gain this functionality. When a type is immutable, meaning the data contained in the instance cannot be changed, overloading operator == to compare value equality instead of reference equality can be useful because, as immutable objects, they can be considered the same as long as they have the same value. Overriding operator==
in non-immutable types is not recommended.
IEquatable文档也很清楚
Defines a generalized method that a value type or class implements to create a type-specific method for determining equality of instances.
在 .NET(以及 Java)中进行相等性测试的一个主要困难是有两个有用的等价关系,每个都基于一个可以对任何 class 对象合理提出的问题,但是 .NET 对于应该由 Equals
和 GetHashCode
应该回答的问题或关系进行封装并不一致。问题是:
无论你发生什么事,你是否永远永远等同于某个特定引用所标识的对象。
你会认为自己等同于某个特定引用所标识的对象,除非或直到引用你的东西做了会影响这种等价的事情。
对于不可变对象,两种关系都应测试值是否相等。对于可变对象,第一个问题应测试引用等价性,第二个问题应测试值相等性。对于持有对可变类型对象的引用但没有人会改变的不可变对象,这两个问题都应测试该封装对象的值相等性。
我个人的建议是可变对象不覆盖 Object.Equals,但它们提供静态 属性,returns 和 IEqualityComparer
来测试值相等性。这将需要
任何不可变地封装可变对象的对象都必须
获取 IEqualityComparer
以能够报告封装对象的
值等价关系本身,但具有 IEqualityComparer
可以将这些东西存储在例如Dictionary
已提供
它们永远不会被修改。