Check this out :
var a = Double.NaN;
Console.WriteLine(a == a);
Console.ReadKey();
Prints "False"
var a = Double.NaN;
Console.WriteLine(a.Equals(a));
Console.ReadKey();
Prints "True"!
Why it prints "True"? Due to floating point numbers specification, value that is NaN is not equal to itself! So it seems that Equals() method is implemented wrong... Am I missing something ?
While you're correct that
NaN == NaN
is false,double.Equals
specially handlesNaN
differently, in a way thatNaN.Equals(NaN)
is true. Here's the .NET 4 implementation of the method from reflector:Equals
is made for things like hashtables. And thus it contract requires thata.Equals(a)
.MSDN states:
What I find strange is that it states "x.Equals(x) returns true, except in cases that involve floating-point types. See IEC 60559:1989, Binary Floating-point Arithmetic for Microprocessor Systems." but at the same time requires that NaN equals NaN. So why did they put that exception in? Because of different NaNs?
In a similar way when using an
IComparer<double>
the floating-point standard must be violated too. SinceIComparer
requires a consistent total ordering.If I were to venture a guess, it might be that this is to support the use of
double
values as keys in a dictionary.If
x.Equals(y)
returnedfalse
forx = double.NaN
andy = double.NaN
, then you could have code like this:I think the majority of developers would find this behavior rather unintuitive. But what would be even more intuitive would be this:
Basically, with an implementation of
Equals
that never returnstrue
for a certain value, what you would have is a type capable of providing keys with the following bizarre behavior:ContainsKey
, and therefore...Remove
Remember that
Equals
is very closely related toGetHashCode
for this very reason (the C# compiler even warns you if you've overridden one without the other)—a big part of why they're there in the first place is to facilitate the use of types as hash table keys.Like I said, it's just a guess.
Check out this link for more information on when to use
==
's orEquals
. Written by the illustrious leader Jon Skeet.I found an article addressing your question: .NET Security Blog: Why == and the Equals Method Return Different Results for Floating Point Values
Update: The full text of section 8.2.5 from the CLI spec (ECMA-335) sheds some more light on this. I've copied the relevant bits here:
The above does not specify the properties of the
==
operator at all (except for the final note); it is primarily defining the behavior ofReferenceEquals
andEquals
. For the behavior of the==
operator, the C# language spec (ECMA-334) (section 14.9.2) is clear about how to treat NaN values: