Search code examples
c#iequatable

How to test for NaN with generics (or why NaN.Equals(NaN) == true)?


I need to find min and max values in an array (not taking into for possible NaN values in this array).

This would be easy only working with double, but these FindMin and FindMax functions have to work with generics types.

I have tried to test for generic NaNs in this way:

bool isNaN<T>(T value) where T : IEquatable<T>
{
    return !value.Equals(value);
}

but Equals is returning true for double.NaN ??!!

I have a workaround like this for now:

bool isNaN<T>(T value) where T : IEquatable<T>
{
    var d = value as double?;
    if (d.HasValue) { return double.IsNaN(d.Value); }

    return !value.Equals(value);
}

My question is more about understanding why first solution did not work, is this a bug ?

You can find small test code here


Solution

  • but Equals is returning true for double.NaN

    Yes. And it does regardless of generics:

    double x = double.NaN;
    Console.WriteLine(x.Equals(x)); // True
    Console.WriteLine(x == x); // False
    

    Note that if the second line printed False, that would either make the IEquatable<T>.Equals inconsistent with the Equals(object) override, or you'd have to make Equals(object) violate the reflexivity requirement of object.Equals(object).

    Basically this sort of thing is nasty whatever you do with it.

    Given that you're trying to find max/min values, you might want to try using IComparable<T> instead of IEquatable<T> - that may well let you detect NaN in other ways. (I don't have time to check right now.)