Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Not able to compare NAN using Expression

I'm using Expression to compare values and i'm using the below code,

Below method creating lambda expression.

    public static class Test
{
    public static Expression<Func<T, bool>> TransformToPredicate<T>(Expression<Func<T, double>> getvalue, double value)
    {
        System.Linq.Expressions.Expression equals = System.Linq.Expressions.Expression.Equal(getvalue.Body,
                                             System.Linq.Expressions.Expression.Constant(value));
        return System.Linq.Expressions.Expression.Lambda<Func<T, bool>>(equals, getvalue.Parameters);
    }
}

In the below code while comparing Nan with Nan value it returns false. How to overcome this when using Expressioons? I need do this in more generic way?

           Employee emp = new Employee();
        emp.SickLeaveHours = double.NaN;
        Expression<Func<Employee, double>> getfunc = x => x.SickLeaveHours;
        var predicate = Test.TransformToPredicate<Employee>(getfunc, double.NaN);
        var func = predicate.Compile();
        var flag = func(emp);

Below code works fine when i use other than Nan value.

            Employee emp = new Employee();
        emp.SickLeaveHours = 10.0;
        Expression<Func<Employee, double>> getfunc = x => x.SickLeaveHours;
        var predicate = Test.TransformToPredicate<Employee>(getfunc, 10.0);
        var func = predicate.Compile();
        var flag = func(emp);

I know double.Nan == double.Nan will return false and we have to use either double.IsNAN or value != value. But i'm not sure how to do this when using Expressions.

like image 418
Sivakumar Avatar asked Jan 29 '26 08:01

Sivakumar


1 Answers

You are comparing by object reference. That is why you always get false returned. However every type provides Equals() method. In order to compare two double or any two same types, you should call their Equals function. Calling equals function is not the same as Expression.Equal.

Here is a demo:

var wrong =
    System.Linq.Expressions.Expression.Lambda<Func<bool>>(
    System.Linq.Expressions.Expression.Equal(System.Linq.Expressions.Expression.Constant(double.NaN),
    System.Linq.Expressions.Expression.Constant(double.NaN))).Compile();

// is always false
bool result = wrong();

ConstantExpression first = System.Linq.Expressions.Expression.Constant(double.NaN, typeof(double));
ConstantExpression second = System.Linq.Expressions.Expression.Constant(double.NaN, typeof(double));

var right =
    System.Linq.Expressions.Expression.Lambda<Func<bool>>(
    System.Linq.Expressions.Expression.Call(first, first.Type.GetMethod("Equals", new[] { second.Type }), second)).Compile();

// will always be true
result = right();
like image 195
dev hedgehog Avatar answered Jan 30 '26 21:01

dev hedgehog