1

Let's consider Polygon class. Check for equality should compare references most of the time, but there are many situations where value equality comes in handy (like when one compares two polygons with Assert.AreEqual).

My idea is to make value equality somewhat secondary to reference equality. In this case it's pretty obvious that ==operator should keep its default reference check implementation.

What about object.Equals() and IEquatable<Polygon>.Equals() then? MSDN doesn't imply that == and .Equals() should do the same but still - wouldn't it make the behavior of Polygon objects too ambiguous?

Also, the Polygon class is mutable.

Hamid Pourjam
  • 18,954
  • 8
  • 53
  • 67
matt-pielat
  • 1,279
  • 3
  • 16
  • 32
  • they are not the same..`long story short` `.Equals used for object equality` `== used for checking equality of a value` do a google search for deeper clarification. why do people ask questions here that they can easily find the answer buy doing a simple google search `I'm just Curious` – MethodMan Nov 13 '15 at 21:20
  • I don't fault OP for asking this question here. I find that SO is a far more reputable source for informed answers than a Google search. And, as he says, MSDN is not always clear about these things. – Mike Hofer Nov 13 '15 at 21:22
  • @MikeHofer The question isn't *on topic* on SO. – Servy Nov 13 '15 at 21:31
  • See also related discussions at [Difference between Equals/equals and == operator?](https://stackoverflow.com/q/971954), [What is the difference between == and Equals() for primitives in C#?](https://stackoverflow.com/q/21273890), and [C# .Equals(), .ReferenceEquals() and == operator](https://stackoverflow.com/q/3869601) (those three are not exactly the same question, but the ample discussion in each does wind up addressing the question above as well). – Peter Duniho Nov 14 '15 at 00:56

2 Answers2

2

MSDN is almost clear about it

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 documentation is also very clear

Defines a generalized method that a value type or class implements to create a type-specific method for determining equality of instances.

Hamid Pourjam
  • 18,954
  • 8
  • 53
  • 67
  • I don't want to override `==`. I'm asking whether overriding `.Equals()` (to make it compare by value) in a mutable class doesn't introduce ambiguity. And considering that value equality check is ideologically "secondary" to reference check. – matt-pielat Nov 13 '15 at 21:30
1

A major difficulty with equality testing in .NET (and also Java) is that there are two useful equivalence relations, each based on a question that can be sensibly asked of any class object, but .NET isn't consistent about which question or relationship should be encapsulated by Equals and GetHashCode supposed to answer. The questions are:

  1. Will you always and forever be equivalent to the object identified by some particular reference, no matter what happens to you.

  2. Will you consider yourself equivalent to the object identified by some particular reference unless or until something with a reference to you does something that would affect that equivalence.

For immutable objects, both relationships should test value equality. For mutable objects, the first question should test referential equivalence and the second should test value equality. For an immutable object which holds a reference to an object which is of mutable type, but which nobody will ever mutate, both questions should test value equality of that encapsulated object.

My personal recommendation would be that mutable objects not override Object.Equals, but that they provide a static property that returns an IEqualityComparer which tests value equality. This would require that any object that immutably encapsulates the mutable object will have to get that IEqualityComparer to be able to report the encapsulated object's value-equivalence relation as its own, but having an IEqualityComparer would make it possible to store such things in e.g. a Dictionary provided they are never modified.

supercat
  • 69,493
  • 7
  • 143
  • 184