Check this out :
var a = Double.NaN;
Console.WriteLine(a == a);
Console.ReadKey();
Prints \"False\"
var a
Equals is made for things like hashtables. And thus it contract requires that a.Equals(a).
MSDN states:
The following statements must be true for all implementations of the Equals method. In the list, x, y, and z represent object references that are not null.
x.Equals(x) returns true, except in cases that involve floating-point types. See IEC 60559:1989, Binary Floating-point Arithmetic for Microprocessor Systems.
x.Equals(y) returns the same value as y.Equals(x).
x.Equals(y) returns true if both x and y are NaN.
If (x.Equals(y) && y.Equals(z)) returns true, then x.Equals(z) returns true.
Successive calls to x.Equals(y) return the same value as long as the objects referenced by x and y are not modified.
x.Equals(null) returns false.
See GetHashCode for additional required behaviors pertaining to the Equals method.
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 the floating-point standard must be violated too. Since IComparer requires a consistent total ordering.